Apple: Handle generation and comsuption of text-based stubs (.tbd files)

Fixes: #24123
stage/master/nightly/2023/03/02
Marc Chevrier 2023-02-01 17:58:30 +01:00
parent fcbd723a50
commit ede33f30cf
84 changed files with 2054 additions and 168 deletions

View File

@ -158,6 +158,9 @@ that may be installed:
``.lib``, in contrast to the ``.dll`` libraries that go to ``RUNTIME``);
* On AIX, the *linker import file* created for executables with
:prop_tgt:`ENABLE_EXPORTS` enabled.
* On macOS, the *linker import file* created for shared libraries with
:prop_tgt:`ENABLE_EXPORTS` enabled (except when marked as ``FRAMEWORK``,
see below).
``LIBRARY``
Target artifacts of this kind include:
@ -308,6 +311,11 @@ the following additional arguments:
value of ``COMPONENT``. It is an error to use this parameter outside of a
``LIBRARY`` block.
.. versionchanged:: 3.27
This parameter is also usable for an ``ARCHIVE`` block to manage
the linker import file created, on macOS, for shared libraries with
:prop_tgt:`ENABLE_EXPORTS` enabled.
Consider the following example:
.. code-block:: cmake
@ -342,6 +350,11 @@ the following additional arguments:
option installs nothing. It is an error to use this parameter outside of a
``LIBRARY`` block.
.. versionchanged:: 3.27
This parameter is also usable for an ``ARCHIVE`` block to manage
the linker import file created, on macOS, for shared libraries with
:prop_tgt:`ENABLE_EXPORTS` enabled.
When ``NAMELINK_ONLY`` is given, either ``NAMELINK_COMPONENT`` or
``COMPONENT`` may be used to specify the installation component of the
namelink, but ``COMPONENT`` should generally be preferred.
@ -355,6 +368,11 @@ the following additional arguments:
installs the library. It is an error to use this parameter outside of a
``LIBRARY`` block.
.. versionchanged:: 3.27
This parameter is also usable for an ``ARCHIVE`` block to manage
the linker import file created, on macOS, for shared libraries with
:prop_tgt:`ENABLE_EXPORTS` enabled.
If ``NAMELINK_SKIP`` is specified, ``NAMELINK_COMPONENT`` has no effect. It
is not recommended to use ``NAMELINK_SKIP`` in conjunction with
``NAMELINK_COMPONENT``.

View File

@ -797,6 +797,10 @@ An *archive* output artifact of a buildsystem target may be:
created by the :command:`add_executable` command when its
:prop_tgt:`ENABLE_EXPORTS` target property is set.
* On macOS: the linker import file (e.g. ``.tbd``) of a shared library target
created by the :command:`add_library` command with the ``SHARED`` option and
when its :prop_tgt:`ENABLE_EXPORTS` target property is set.
The :prop_tgt:`ARCHIVE_OUTPUT_DIRECTORY` and :prop_tgt:`ARCHIVE_OUTPUT_NAME`
target properties may be used to control archive output artifact locations
and names in the build tree.

View File

@ -1503,6 +1503,76 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
.. genex:: $<TARGET_IMPORT_FILE:tgt>
.. versionadded:: 3.27
Full path to the linker import file. On DLL platforms, it would be the
``.lib`` file. On AIX, for the executables, and on macOS, for the shared
libraries, it could be, respectively, the ``.imp`` or ``.tbd`` import file,
depending of the value of :prop_tgt:`ENABLE_EXPORTS` property.
An empty string is returned when there is no import file associated with the
target.
.. genex:: $<TARGET_IMPORT_FILE_BASE_NAME:tgt>
.. versionadded:: 3.27
Base name of file linker import file of the target ``tgt`` without prefix and
suffix. For example, if target file name is ``libbase.tbd``, the base name is
``base``.
See also the :prop_tgt:`OUTPUT_NAME` and :prop_tgt:`ARCHIVE_OUTPUT_NAME`
target properties and their configuration specific variants
:prop_tgt:`OUTPUT_NAME_<CONFIG>` and :prop_tgt:`ARCHIVE_OUTPUT_NAME_<CONFIG>`.
The :prop_tgt:`<CONFIG>_POSTFIX` and :prop_tgt:`DEBUG_POSTFIX` target
properties can also be considered.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_IMPORT_FILE_PREFIX:tgt>
.. versionadded:: 3.27
Prefix of the import file of the target ``tgt``.
See also the :prop_tgt:`IMPORT_PREFIX` target property.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_IMPORT_FILE_SUFFIX:tgt>
.. versionadded:: 3.27
Suffix of the import file of the target ``tgt``.
The suffix corresponds to the file extension (such as ".lib" or ".tbd").
See also the :prop_tgt:`IMPORT_SUFFIX` target property.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_IMPORT_FILE_NAME:tgt>
.. versionadded:: 3.27
Name of the import file of the target target ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_IMPORT_FILE_DIR:tgt>
Directory of the import file of the target ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_FILE:tgt>
File used when linking to the ``tgt`` target. This will usually
@ -1510,13 +1580,22 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
but for a shared library on DLL platforms, it would be the ``.lib``
import library associated with the DLL.
.. versionadded:: 3.27
On macOS, it could be the ``.tbd`` import file associated with the shared
library, depending of the value of :prop_tgt:`ENABLE_EXPORTS` property.
This generator expression is equivalent to
:genex:`$<TARGET_LINKER_LIBRARY_FILE>` or
:genex:`$<TARGET_LINKER_IMPORT_FILE>` generator expressions, depending of the
characteristics of the target and the platform.
.. genex:: $<TARGET_LINKER_FILE_BASE_NAME:tgt>
.. versionadded:: 3.15
Base name of file used to link the target ``tgt``, i.e.
``$<TARGET_LINKER_FILE_NAME:tgt>`` without prefix and suffix. For example,
if target file name is ``libbase.a``, the base name is ``base``.
:genex:`$<TARGET_LINKER_FILE_NAME:tgt>` without prefix and suffix. For
example, if target file name is ``libbase.a``, the base name is ``base``.
See also the :prop_tgt:`OUTPUT_NAME`, :prop_tgt:`ARCHIVE_OUTPUT_NAME`,
and :prop_tgt:`LIBRARY_OUTPUT_NAME` target properties and their configuration
@ -1570,9 +1649,151 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
.. genex:: $<TARGET_LINKER_LIBRARY_FILE:tgt>
.. versionadded:: 3.27
File used when linking o the ``tgt`` target is done using directly the
library, and not an import file. This will usually be the library that
``tgt`` represents (``.a``, ``.so``, ``.dylib``). So, on DLL platforms, it
will be an empty string.
.. genex:: $<TARGET_LINKER_LIBRARY_FILE_BASE_NAME:tgt>
.. versionadded:: 3.27
Base name of library file used to link the target ``tgt``, i.e.
:genex:`$<TARGET_LINKER_LIBRARY_FILE_NAME:tgt>` without prefix and suffix.
For example, if target file name is ``libbase.a``, the base name is ``base``.
See also the :prop_tgt:`OUTPUT_NAME`, :prop_tgt:`ARCHIVE_OUTPUT_NAME`,
and :prop_tgt:`LIBRARY_OUTPUT_NAME` target properties and their configuration
specific variants :prop_tgt:`OUTPUT_NAME_<CONFIG>`,
:prop_tgt:`ARCHIVE_OUTPUT_NAME_<CONFIG>` and
:prop_tgt:`LIBRARY_OUTPUT_NAME_<CONFIG>`.
The :prop_tgt:`<CONFIG>_POSTFIX` and :prop_tgt:`DEBUG_POSTFIX` target
properties can also be considered.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_LIBRARY_FILE_PREFIX:tgt>
.. versionadded:: 3.27
Prefix of the library file used to link target ``tgt``.
See also the :prop_tgt:`PREFIX` target property.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_LIBRARY_FILE_SUFFIX:tgt>
.. versionadded:: 3.27
Suffix of the library file used to link target ``tgt``.
The suffix corresponds to the file extension (such as ".a" or ".dylib").
See also the :prop_tgt:`SUFFIX` target property.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_LIBRARY_FILE_NAME:tgt>
.. versionadded:: 3.27
Name of the library file used to link target ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_LIBRARY_FILE_DIR:tgt>
.. versionadded:: 3.27
Directory of the library file used to link target ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_IMPORT_FILE:tgt>
.. versionadded:: 3.27
File used when linking to the ``tgt`` target is done using an import
file. This will usually be the import file that ``tgt`` represents
(``.lib``, ``.tbd``). So, when no import file is involved in the link step,
an empty string is returned.
.. genex:: $<TARGET_LINKER_IMPORT_FILE_BASE_NAME:tgt>
.. versionadded:: 3.27
Base name of the import file used to link the target ``tgt``, i.e.
:genex:`$<TARGET_LINKER_IMPORT_FILE_NAME:tgt>` without prefix and suffix.
For example, if target file name is ``libbase.tbd``, the base name is ``base``.
See also the :prop_tgt:`OUTPUT_NAME` and :prop_tgt:`ARCHIVE_OUTPUT_NAME`,
target properties and their configuration
specific variants :prop_tgt:`OUTPUT_NAME_<CONFIG>` and
:prop_tgt:`ARCHIVE_OUTPUT_NAME_<CONFIG>`.
The :prop_tgt:`<CONFIG>_POSTFIX` and :prop_tgt:`DEBUG_POSTFIX` target
properties can also be considered.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_IMPORT_FILE_PREFIX:tgt>
.. versionadded:: 3.27
Prefix of the import file used to link target ``tgt``.
See also the :prop_tgt:`IMPORT_PREFIX` target property.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_IMPORT_FILE_SUFFIX:tgt>
.. versionadded:: 3.27
Suffix of the import file used to link target ``tgt``.
The suffix corresponds to the file extension (such as ".lib" or ".tbd").
See also the :prop_tgt:`IMPORT_SUFFIX` target property.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_IMPORT_FILE_NAME:tgt>
.. versionadded:: 3.27
Name of the import file used to link target ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_LINKER_IMPORT_FILE_DIR:tgt>
.. versionadded:: 3.27
Directory of the import file used to link target ``tgt``.
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_SONAME_FILE:tgt>
File with soname (``.so.3``) where ``tgt`` is the name of a target.
.. genex:: $<TARGET_SONAME_FILE_NAME:tgt>
Name of file with soname (``.so.3``).
@ -1582,11 +1803,35 @@ In the following, the phrase "the ``tgt`` filename" means the name of the
.. genex:: $<TARGET_SONAME_FILE_DIR:tgt>
Directory of with soname (``.so.3``).
Directory of file with soname (``.so.3``).
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on (see policy :policy:`CMP0112`).
.. genex:: $<TARGET_SONAME_IMPORT_FILE:tgt>
.. versionadded:: 3.27
Import file with soname (``.3.tbd``) where ``tgt`` is the name of a target.
.. genex:: $<TARGET_SONAME_IMPORT_FILE_NAME:tgt>
.. versionadded:: 3.27
Name of the import file with soname (``.3.tbd``).
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_SONAME_IMPORT_FILE_DIR:tgt>
.. versionadded:: 3.27
Directory of the import file with soname (``.3.tbd``).
Note that ``tgt`` is not added as a dependency of the target this
expression is evaluated on.
.. genex:: $<TARGET_PDB_FILE:tgt>
.. versionadded:: 3.1

View File

@ -428,6 +428,7 @@ Variables that Control the Build
/variable/CMAKE_DEPENDS_USE_COMPILER
/variable/CMAKE_DISABLE_PRECOMPILE_HEADERS
/variable/CMAKE_ENABLE_EXPORTS
/variable/CMAKE_EXECUTABLE_ENABLE_EXPORTS
/variable/CMAKE_EXE_LINKER_FLAGS
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT
@ -507,6 +508,7 @@ Variables that Control the Build
/variable/CMAKE_POSITION_INDEPENDENT_CODE
/variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY
/variable/CMAKE_RUNTIME_OUTPUT_DIRECTORY_CONFIG
/variable/CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS
/variable/CMAKE_SHARED_LINKER_FLAGS
/variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG
/variable/CMAKE_SHARED_LINKER_FLAGS_CONFIG_INIT

View File

@ -6,4 +6,7 @@ ARCHIVE_OUTPUT_DIRECTORY
.. |CMAKE_XXX_OUTPUT_DIRECTORY| replace:: :variable:`CMAKE_ARCHIVE_OUTPUT_DIRECTORY`
.. include:: XXX_OUTPUT_DIRECTORY.txt
.. |IDEM| replace:: in the same directory
.. include:: MACOS_IMPORT_FILES.txt
See also the :prop_tgt:`ARCHIVE_OUTPUT_DIRECTORY_<CONFIG>` target property.

View File

@ -5,4 +5,7 @@ ARCHIVE_OUTPUT_NAME
.. |xxx| replace:: archive
.. include:: XXX_OUTPUT_NAME.txt
.. |IDEM| replace:: with the same name
.. include:: MACOS_IMPORT_FILES.txt
See also the :prop_tgt:`ARCHIVE_OUTPUT_NAME_<CONFIG>` target property.

View File

@ -1,7 +1,7 @@
ENABLE_EXPORTS
--------------
Specify whether an executable exports symbols for loadable modules.
Specify whether an executable or a shared library exports symbols.
Normally an executable does not export any symbols because it is the
final program. It is possible for an executable to export symbols to
@ -28,4 +28,29 @@ varies by platform:
automatically bind symbols when the module is loaded.
This property is initialized by the value of the variable
:variable:`CMAKE_ENABLE_EXPORTS` if it is set when a target is created.
:variable:`CMAKE_EXECUTABLE_ENABLE_EXPORTS` if it is set when an executable
target is created.
.. versionadded:: 3.27
On macOS, to link with a shared library (standard one as well as framework),
a linker import file (e.g. a text-based stubs file, with ``.tbd`` extension)
can be used instead of the shared library itself.
The generation of these linker import files, as well as the consumption, is
controlled by this property. When this property is set to true, CMake will
generate a ``.tbd`` file for each shared library created by
:command:`add_library` command. This allow other targets to use this ``.tbd``
file to link to the library with the :command:`target_link_libraries`
command.
.. note::
For compatibility purpose, this property will be ignored if
:prop_tgt:`XCODE_ATTRIBUTE_GENERATE_TEXT_BASED_STUBS <XCODE_ATTRIBUTE_<an-attribute>>`
target property or the
:variable:`CMAKE_XCODE_ATTRIBUTE_GENERATE_TEXT_BASED_STUBS <CMAKE_XCODE_ATTRIBUTE_<an-attribute>>`
variable is set to ``NO``.
This property is initialized by the value of the variable
:variable:`CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS` if it is set when a shared
library target is created.

View File

@ -3,7 +3,13 @@ IMPORTED_IMPLIB
Full path to the import library for an ``IMPORTED`` target.
Set this to the location of the ``.lib`` part of a Windows DLL, or on
AIX set it to an import file created for executables that export symbols
(see the :prop_tgt:`ENABLE_EXPORTS` target property).
Ignored for non-imported targets.
This property may be set:
* On DLL platforms, to the location of the ``.lib`` part of the DLL.
* On AIX, to an import file (e.g. ``.imp``) created for executables that export
symbols (see the :prop_tgt:`ENABLE_EXPORTS` target property).
* On macOS, to an import file (e.g. ``.tbd``) created for shared libraries (see
the :prop_tgt:`ENABLE_EXPORTS` target property). For frameworks this is the
location of the ``.tbd`` file symlink just inside the framework folder.
This property is ignored for non-imported targets.

View File

@ -27,5 +27,5 @@ selected and its :prop_tgt:`IMPORTED_LOCATION_<CONFIG>` value used.
To get the location of an imported target read one of the :prop_tgt:`LOCATION`
or ``LOCATION_<CONFIG>`` properties.
For platforms with import libraries (e.g. Windows) see also
For platforms with import libraries (e.g. Windows, AIX or macOS) see also
:prop_tgt:`IMPORTED_IMPLIB`.

View File

@ -0,0 +1,12 @@
.. note::
On macOS, this property will be ignored for the linker import files (e.g.
``.tbd`` files, see :prop_tgt:`ENABLE_EXPORTS` property for details) when:
* The :prop_tgt:`FRAMEWORK` is set, because the framework layout cannot be
changed.
* The :generator:`Xcode` generator is used, due to the limitations and
constraints of the ``Xcode`` tool.
In both cases, the linker import files will be generated |IDEM| as the shared
library.

View File

@ -0,0 +1,6 @@
Apple-tbd-files-management
--------------------------
* Support for text-based stubs (i.e. ``.tbd`` files) was added on macOS
platform. This capability is managed through the :prop_tgt:`ENABLE_EXPORTS`
property.

View File

@ -8,3 +8,7 @@ Specify whether executables export symbols for loadable modules.
This variable is used to initialize the :prop_tgt:`ENABLE_EXPORTS` target
property for executable targets when they are created by calls to the
:command:`add_executable` command. See the property documentation for details.
This command has been superseded by the
:variable:`CMAKE_EXECUTABLE_ENABLE_EXPORTS` command. It is provided for
compatibility with older CMake code.

View File

@ -0,0 +1,12 @@
CMAKE_EXECUTABLE_ENABLE_EXPORTS
-------------------------------
.. versionadded:: 3.27
Specify whether executables export symbols for loadable modules.
This variable is used to initialize the :prop_tgt:`ENABLE_EXPORTS` target
property for executable targets when they are created by calls to the
:command:`add_executable` command. See the property documentation for details.
This variable supersede the :variable:`CMAKE_ENABLE_EXPORTS` variable.

View File

@ -0,0 +1,10 @@
CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS
-----------------------------------
.. versionadded:: 3.27
Specify whether shared library generates an import file.
This variable is used to initialize the :prop_tgt:`ENABLE_EXPORTS` target
property for shared library targets when they are created by calls to the
:command:`add_library` command. See the property documentation for details.

View File

@ -6,6 +6,7 @@ set(CMAKE_RANLIB "@CMAKE_RANLIB@")
set(CMAKE_ASM@ASM_DIALECT@_COMPILER_RANLIB "@_CMAKE_ASM_COMPILER_RANLIB@")
set(CMAKE_LINKER "@CMAKE_LINKER@")
set(CMAKE_MT "@CMAKE_MT@")
set(CMAKE_TAPI "@CMAKE_TAPI@")
set(CMAKE_ASM@ASM_DIALECT@_COMPILER_LOADED 1)
set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ID "@_CMAKE_ASM_COMPILER_ID@")
set(CMAKE_ASM@ASM_DIALECT@_COMPILER_VERSION "@_CMAKE_ASM_COMPILER_VERSION@")

View File

@ -27,6 +27,7 @@ set(CMAKE_RANLIB "@CMAKE_RANLIB@")
set(CMAKE_C_COMPILER_RANLIB "@CMAKE_C_COMPILER_RANLIB@")
set(CMAKE_LINKER "@CMAKE_LINKER@")
set(CMAKE_MT "@CMAKE_MT@")
set(CMAKE_TAPI "@CMAKE_TAPI@")
set(CMAKE_COMPILER_IS_GNUCC @CMAKE_COMPILER_IS_GNUCC@)
set(CMAKE_C_COMPILER_LOADED 1)
set(CMAKE_C_COMPILER_WORKS @CMAKE_C_COMPILER_WORKS@)

View File

@ -28,6 +28,7 @@ set(CMAKE_RANLIB "@CMAKE_RANLIB@")
set(CMAKE_CXX_COMPILER_RANLIB "@CMAKE_CXX_COMPILER_RANLIB@")
set(CMAKE_LINKER "@CMAKE_LINKER@")
set(CMAKE_MT "@CMAKE_MT@")
set(CMAKE_TAPI "@CMAKE_TAPI@")
set(CMAKE_COMPILER_IS_GNUCXX @CMAKE_COMPILER_IS_GNUCXX@)
set(CMAKE_CXX_COMPILER_LOADED 1)
set(CMAKE_CXX_COMPILER_WORKS @CMAKE_CXX_COMPILER_WORKS@)

View File

@ -165,6 +165,7 @@ else()
set(_CMAKE_READELF_NAMES "readelf")
set(_CMAKE_DLLTOOL_NAMES "dlltool")
set(_CMAKE_ADDR2LINE_NAMES "addr2line")
set(_CMAKE_TAPI_NAMES "tapi")
# Prepend toolchain-specific names.
if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang)
@ -201,7 +202,7 @@ else()
list(PREPEND _CMAKE_LINKER_NAMES "armlink")
endif()
list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE)
list(APPEND _CMAKE_TOOL_VARS AR RANLIB STRIP LINKER NM OBJDUMP OBJCOPY READELF DLLTOOL ADDR2LINE TAPI)
endif()
foreach(_CMAKE_TOOL IN LISTS _CMAKE_TOOL_VARS)
@ -225,6 +226,20 @@ if(NOT CMAKE_RANLIB)
set(CMAKE_RANLIB : CACHE INTERNAL "noop for ranlib")
endif()
if(NOT CMAKE_TAPI)
# try to pick-up from Apple toolchain
execute_process(COMMAND xcrun --find tapi
OUTPUT_VARIABLE _xcrun_out
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
RESULT_VARIABLE _xcrun_failed)
if(NOT _xcrun_failed AND EXISTS "${_xcrun_out}")
set_property(CACHE CMAKE_TAPI PROPERTY VALUE "${_xcrun_out}")
endif()
unset(_xcrun_out)
unset(_xcrun_failed)
endif()
if(CMAKE_PLATFORM_HAS_INSTALLNAME)
find_program(CMAKE_INSTALL_NAME_TOOL NAMES ${_CMAKE_TOOLCHAIN_PREFIX}install_name_tool HINTS ${_CMAKE_TOOLCHAIN_LOCATION} NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH)

View File

@ -14,6 +14,7 @@ set(CMAKE_Fortran_SIMULATE_VERSION "@CMAKE_Fortran_SIMULATE_VERSION@")
set(CMAKE_AR "@CMAKE_AR@")
set(CMAKE_Fortran_COMPILER_AR "@CMAKE_Fortran_COMPILER_AR@")
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
set(CMAKE_TAPI "@CMAKE_TAPI@")
set(CMAKE_Fortran_COMPILER_RANLIB "@CMAKE_Fortran_COMPILER_RANLIB@")
set(CMAKE_COMPILER_IS_GNUG77 @CMAKE_COMPILER_IS_GNUG77@)
set(CMAKE_Fortran_COMPILER_LOADED 1)

View File

@ -58,3 +58,4 @@ set(CMAKE_RANLIB "@CMAKE_RANLIB@")
set(CMAKE_HIP_COMPILER_RANLIB "@CMAKE_HIP_COMPILER_RANLIB@")
set(CMAKE_LINKER "@CMAKE_LINKER@")
set(CMAKE_MT "@CMAKE_MT@")
set(CMAKE_TAPI "@CMAKE_TAPI@")

View File

@ -25,6 +25,7 @@ set(CMAKE_RANLIB "@CMAKE_RANLIB@")
set(CMAKE_OBJC_COMPILER_RANLIB "@CMAKE_OBJC_COMPILER_RANLIB@")
set(CMAKE_LINKER "@CMAKE_LINKER@")
set(CMAKE_MT "@CMAKE_MT@")
set(CMAKE_TAPI "@CMAKE_TAPI@")
set(CMAKE_COMPILER_IS_GNUOBJC @CMAKE_COMPILER_IS_GNUOBJC@)
set(CMAKE_OBJC_COMPILER_LOADED 1)
set(CMAKE_OBJC_COMPILER_WORKS @CMAKE_OBJC_COMPILER_WORKS@)

View File

@ -26,6 +26,7 @@ set(CMAKE_RANLIB "@CMAKE_RANLIB@")
set(CMAKE_OBJCXX_COMPILER_RANLIB "@CMAKE_OBJCXX_COMPILER_RANLIB@")
set(CMAKE_LINKER "@CMAKE_LINKER@")
set(CMAKE_MT "@CMAKE_MT@")
set(CMAKE_TAPI "@CMAKE_TAPI@")
set(CMAKE_COMPILER_IS_GNUOBJCXX @CMAKE_COMPILER_IS_GNUOBJCXX@)
set(CMAKE_OBJCXX_COMPILER_LOADED 1)
set(CMAKE_OBJCXX_COMPILER_WORKS @CMAKE_OBJCXX_COMPILER_WORKS@)

View File

@ -45,6 +45,8 @@ set(CMAKE_SHARED_LIBRARY_SUFFIX ".dylib")
set(CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES ".tbd" ".so")
set(CMAKE_SHARED_MODULE_PREFIX "lib")
set(CMAKE_SHARED_MODULE_SUFFIX ".so")
set(CMAKE_APPLE_IMPORT_FILE_PREFIX "lib")
set(CMAKE_APPLE_IMPORT_FILE_SUFFIX ".tbd")
set(CMAKE_MODULE_EXISTS 1)
set(CMAKE_DL_LIBS "")
if(NOT "${_CURRENT_OSX_VERSION}" VERSION_LESS "10.5")
@ -108,6 +110,9 @@ foreach(lang C CXX Fortran OBJC OBJCXX)
set(CMAKE_${lang}_FRAMEWORK_SEARCH_FLAG -F)
endforeach()
# To generate text-based stubs
set(CMAKE_CREATE_TEXT_STUBS "<CMAKE_TAPI> stubify -isysroot <CMAKE_OSX_SYSROOT> -o <TARGET_IMPLIB> <TARGET>")
# Defines LINK_LIBRARY features for frameworks
set(CMAKE_LINK_LIBRARY_USING_FRAMEWORK "LINKER:-framework,<LIBRARY>")
set(CMAKE_LINK_LIBRARY_USING_FRAMEWORK_SUPPORTED TRUE)

View File

@ -25,7 +25,6 @@
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmValue.h"
cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)

View File

@ -72,6 +72,10 @@ SETUP_LANGUAGE(swift_properties, Swift);
std::string const kCMAKE_CUDA_ARCHITECTURES = "CMAKE_CUDA_ARCHITECTURES";
std::string const kCMAKE_CUDA_RUNTIME_LIBRARY = "CMAKE_CUDA_RUNTIME_LIBRARY";
std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS";
std::string const kCMAKE_EXECUTABLE_ENABLE_EXPORTS =
"CMAKE_EXECUTABLE_ENABLE_EXPORTS";
std::string const kCMAKE_SHARED_LIBRARY_ENABLE_EXPORTS =
"CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS";
std::string const kCMAKE_HIP_ARCHITECTURES = "CMAKE_HIP_ARCHITECTURES";
std::string const kCMAKE_HIP_RUNTIME_LIBRARY = "CMAKE_HIP_RUNTIME_LIBRARY";
std::string const kCMAKE_ISPC_INSTRUCTION_SETS = "CMAKE_ISPC_INSTRUCTION_SETS";
@ -997,6 +1001,8 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
vars.insert(kCMAKE_CUDA_ARCHITECTURES);
vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY);
vars.insert(kCMAKE_ENABLE_EXPORTS);
vars.insert(kCMAKE_EXECUTABLE_ENABLE_EXPORTS);
vars.insert(kCMAKE_SHARED_LIBRARY_ENABLE_EXPORTS);
vars.insert(kCMAKE_HIP_ARCHITECTURES);
vars.insert(kCMAKE_HIP_RUNTIME_LIBRARY);
vars.insert(kCMAKE_ISPC_INSTRUCTION_SETS);

View File

@ -254,7 +254,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
if (target->HasImportLibrary(config)) {
std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
std::string value =
target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact);
target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact, true);
if (mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
target->GetImplibGNUtoMS(config, value, value,
"${CMAKE_IMPORT_LIBRARY_SUFFIX}");

View File

@ -1063,7 +1063,8 @@ void cmExportFileGenerator::GenerateImportTargetCode(
}
// Mark the imported executable if it has exports.
if (target->IsExecutableWithExports()) {
if (target->IsExecutableWithExports() ||
(target->IsSharedLibraryWithExports() && target->HasImportLibrary(""))) {
os << "set_property(TARGET " << targetName
<< " PROPERTY ENABLE_EXPORTS 1)\n";
}

View File

@ -409,7 +409,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
// Append the installed file name.
value += cmInstallTargetGenerator::GetInstallFilename(
target, config, cmInstallTargetGenerator::NameImplib);
target, config, cmInstallTargetGenerator::NameImplibReal);
// Store the property.
properties[prop] = value;
@ -430,6 +430,19 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
properties[prop] = cmJoin(objects, ";");
importedLocations.insert(prop);
} else {
if (target->IsFrameworkOnApple() && target->HasImportLibrary(config)) {
// store as well IMPLIB value
auto importProp = cmStrCat("IMPORTED_IMPLIB", suffix);
auto importValue =
cmStrCat(value,
cmInstallTargetGenerator::GetInstallFilename(
target, config, cmInstallTargetGenerator::NameImplibReal));
// Store the property.
properties[importProp] = importValue;
importedLocations.insert(importProp);
}
// Construct the property name.
std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);

View File

@ -2658,10 +2658,14 @@ static const struct InstallPrefixNode : public cmGeneratorExpressionNode
class ArtifactDirTag;
class ArtifactLinkerTag;
class ArtifactLinkerLibraryTag;
class ArtifactLinkerImportTag;
class ArtifactNameTag;
class ArtifactImportTag;
class ArtifactPathTag;
class ArtifactPdbTag;
class ArtifactSonameTag;
class ArtifactSonameImportTag;
class ArtifactBundleDirTag;
class ArtifactBundleDirNameTag;
class ArtifactBundleContentDirTag;
@ -2770,6 +2774,38 @@ struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
}
};
template <>
struct TargetFilesystemArtifactResultCreator<ArtifactSonameImportTag>
{
static std::string Create(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
// The target soname file (.so.1).
if (target->IsDLLPlatform()) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_SONAME_IMPORT_FILE is not allowed "
"for DLL target platforms.");
return std::string();
}
if (target->GetType() != cmStateEnums::SHARED_LIBRARY) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_SONAME_IMPORT_FILE is allowed only for "
"SHARED libraries.");
return std::string();
}
if (target->HasImportLibrary(context->Config)) {
return cmStrCat(target->GetDirectory(
context->Config, cmStateEnums::ImportLibraryArtifact),
'/',
target->GetSOName(context->Config,
cmStateEnums::ImportLibraryArtifact));
}
return std::string{};
}
};
template <>
struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
{
@ -2817,7 +2853,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
// The file used to link to the target (.so, .lib, .a).
// The file used to link to the target (.so, .lib, .a) or import file
// (.lib, .tbd).
if (!target->IsLinkable()) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_LINKER_FILE is allowed only for libraries and "
@ -2832,6 +2869,55 @@ struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
}
};
template <>
struct TargetFilesystemArtifactResultCreator<ArtifactLinkerLibraryTag>
{
static std::string Create(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
// The file used to link to the target (.dylib, .so, .a).
if (!target->IsLinkable() ||
target->GetType() == cmStateEnums::EXECUTABLE) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_LINKER_LIBRARY_FILE is allowed only for libraries "
"with ENABLE_EXPORTS.");
return std::string();
}
if (!target->IsDLLPlatform() ||
target->GetType() == cmStateEnums::STATIC_LIBRARY) {
return target->GetFullPath(context->Config,
cmStateEnums::RuntimeBinaryArtifact);
}
return std::string{};
}
};
template <>
struct TargetFilesystemArtifactResultCreator<ArtifactLinkerImportTag>
{
static std::string Create(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
// The file used to link to the target (.lib, .tbd).
if (!target->IsLinkable()) {
::reportError(
context, content->GetOriginalExpression(),
"TARGET_LINKER_IMPORT_FILE is allowed only for libraries and "
"executables with ENABLE_EXPORTS.");
return std::string();
}
if (target->HasImportLibrary(context->Config)) {
return target->GetFullPath(context->Config,
cmStateEnums::ImportLibraryArtifact);
}
return std::string{};
}
};
template <>
struct TargetFilesystemArtifactResultCreator<ArtifactBundleDirTag>
{
@ -2929,6 +3015,21 @@ struct TargetFilesystemArtifactResultCreator<ArtifactNameTag>
}
};
template <>
struct TargetFilesystemArtifactResultCreator<ArtifactImportTag>
{
static std::string Create(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* /*unused*/)
{
if (target->HasImportLibrary(context->Config)) {
return target->GetFullPath(context->Config,
cmStateEnums::ImportLibraryArtifact, true);
}
return std::string{};
}
};
template <typename ArtifactT>
struct TargetFilesystemArtifactResultGetter
{
@ -3054,12 +3155,24 @@ struct TargetFilesystemArtifactNodeGroup
static const TargetFilesystemArtifactNodeGroup<ArtifactNameTag>
targetNodeGroup;
static const TargetFilesystemArtifactNodeGroup<ArtifactImportTag>
targetImportNodeGroup;
static const TargetFilesystemArtifactNodeGroup<ArtifactLinkerTag>
targetLinkerNodeGroup;
static const TargetFilesystemArtifactNodeGroup<ArtifactLinkerLibraryTag>
targetLinkerLibraryNodeGroup;
static const TargetFilesystemArtifactNodeGroup<ArtifactLinkerImportTag>
targetLinkerImportNodeGroup;
static const TargetFilesystemArtifactNodeGroup<ArtifactSonameTag>
targetSoNameNodeGroup;
static const TargetFilesystemArtifactNodeGroup<ArtifactSonameImportTag>
targetSoNameImportNodeGroup;
static const TargetFilesystemArtifactNodeGroup<ArtifactPdbTag>
targetPdbNodeGroup;
@ -3098,6 +3211,22 @@ struct TargetOutputNameArtifactResultGetter<ArtifactNameTag>
}
};
template <>
struct TargetOutputNameArtifactResultGetter<ArtifactImportTag>
{
static std::string Get(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* /*unused*/)
{
if (target->HasImportLibrary(context->Config)) {
return target->GetOutputName(context->Config,
cmStateEnums::ImportLibraryArtifact) +
target->GetFilePostfix(context->Config);
}
return std::string{};
}
};
template <>
struct TargetOutputNameArtifactResultGetter<ArtifactLinkerTag>
{
@ -3105,7 +3234,8 @@ struct TargetOutputNameArtifactResultGetter<ArtifactLinkerTag>
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
// The file used to link to the target (.so, .lib, .a).
// The library file used to link to the target (.so, .lib, .a) or import
// file (.lin, .tbd).
if (!target->IsLinkable()) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_LINKER_FILE_BASE_NAME is allowed only for "
@ -3121,6 +3251,56 @@ struct TargetOutputNameArtifactResultGetter<ArtifactLinkerTag>
}
};
template <>
struct TargetOutputNameArtifactResultGetter<ArtifactLinkerLibraryTag>
{
static std::string Get(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
// The library file used to link to the target (.so, .lib, .a).
if (!target->IsLinkable() ||
target->GetType() == cmStateEnums::EXECUTABLE) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_LINKER_LIBRARY_FILE_BASE_NAME is allowed only for "
"libraries with ENABLE_EXPORTS.");
return std::string();
}
if (!target->IsDLLPlatform() ||
target->GetType() == cmStateEnums::STATIC_LIBRARY) {
return target->GetOutputName(context->Config,
cmStateEnums::ImportLibraryArtifact) +
target->GetFilePostfix(context->Config);
}
return std::string{};
}
};
template <>
struct TargetOutputNameArtifactResultGetter<ArtifactLinkerImportTag>
{
static std::string Get(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
// The import file used to link to the target (.lib, .tbd).
if (!target->IsLinkable()) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_LINKER_IMPORT_FILE_BASE_NAME is allowed only for "
"libraries and executables with ENABLE_EXPORTS.");
return std::string();
}
if (target->HasImportLibrary(context->Config)) {
return target->GetOutputName(context->Config,
cmStateEnums::ImportLibraryArtifact) +
target->GetFilePostfix(context->Config);
}
return std::string{};
}
};
template <>
struct TargetOutputNameArtifactResultGetter<ArtifactPdbTag>
{
@ -3192,15 +3372,27 @@ struct TargetFileBaseNameArtifact : public TargetArtifactBase
static const TargetFileBaseNameArtifact<ArtifactNameTag>
targetFileBaseNameNode;
static const TargetFileBaseNameArtifact<ArtifactImportTag>
targetImportFileBaseNameNode;
static const TargetFileBaseNameArtifact<ArtifactLinkerTag>
targetLinkerFileBaseNameNode;
static const TargetFileBaseNameArtifact<ArtifactLinkerLibraryTag>
targetLinkerLibraryFileBaseNameNode;
static const TargetFileBaseNameArtifact<ArtifactLinkerImportTag>
targetLinkerImportFileBaseNameNode;
static const TargetFileBaseNameArtifact<ArtifactPdbTag>
targetPdbFileBaseNameNode;
class ArtifactFilePrefixTag;
class ArtifactImportFilePrefixTag;
class ArtifactLinkerFilePrefixTag;
class ArtifactLinkerLibraryFilePrefixTag;
class ArtifactLinkerImportFilePrefixTag;
class ArtifactFileSuffixTag;
class ArtifactImportFileSuffixTag;
class ArtifactLinkerFileSuffixTag;
class ArtifactLinkerLibraryFileSuffixTag;
class ArtifactLinkerImportFileSuffixTag;
template <typename ArtifactT>
struct TargetFileArtifactResultGetter
@ -3221,6 +3413,20 @@ struct TargetFileArtifactResultGetter<ArtifactFilePrefixTag>
}
};
template <>
struct TargetFileArtifactResultGetter<ArtifactImportFilePrefixTag>
{
static std::string Get(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent*)
{
if (target->HasImportLibrary(context->Config)) {
return target->GetFilePrefix(context->Config,
cmStateEnums::ImportLibraryArtifact);
}
return std::string{};
}
};
template <>
struct TargetFileArtifactResultGetter<ArtifactLinkerFilePrefixTag>
{
static std::string Get(cmGeneratorTarget* target,
@ -3228,9 +3434,10 @@ struct TargetFileArtifactResultGetter<ArtifactLinkerFilePrefixTag>
const GeneratorExpressionContent* content)
{
if (!target->IsLinkable()) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_LINKER_PREFIX is allowed only for libraries and "
"executables with ENABLE_EXPORTS.");
::reportError(
context, content->GetOriginalExpression(),
"TARGET_LINKER_FILE_PREFIX is allowed only for libraries and "
"executables with ENABLE_EXPORTS.");
return std::string();
}
@ -3243,6 +3450,52 @@ struct TargetFileArtifactResultGetter<ArtifactLinkerFilePrefixTag>
}
};
template <>
struct TargetFileArtifactResultGetter<ArtifactLinkerLibraryFilePrefixTag>
{
static std::string Get(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
if (!target->IsLinkable() ||
target->GetType() == cmStateEnums::EXECUTABLE) {
::reportError(
context, content->GetOriginalExpression(),
"TARGET_LINKER_LIBRARY_FILE_PREFIX is allowed only for libraries "
"with ENABLE_EXPORTS.");
return std::string();
}
if (!target->IsDLLPlatform() ||
target->GetType() == cmStateEnums::STATIC_LIBRARY) {
return target->GetFilePrefix(context->Config,
cmStateEnums::RuntimeBinaryArtifact);
}
return std::string{};
}
};
template <>
struct TargetFileArtifactResultGetter<ArtifactLinkerImportFilePrefixTag>
{
static std::string Get(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
if (!target->IsLinkable()) {
::reportError(
context, content->GetOriginalExpression(),
"TARGET_LINKER_IMPORT_FILE_PREFIX is allowed only for libraries and "
"executables with ENABLE_EXPORTS.");
return std::string();
}
if (target->HasImportLibrary(context->Config)) {
return target->GetFilePrefix(context->Config,
cmStateEnums::ImportLibraryArtifact);
}
return std::string{};
}
};
template <>
struct TargetFileArtifactResultGetter<ArtifactFileSuffixTag>
{
static std::string Get(cmGeneratorTarget* target,
@ -3253,6 +3506,20 @@ struct TargetFileArtifactResultGetter<ArtifactFileSuffixTag>
}
};
template <>
struct TargetFileArtifactResultGetter<ArtifactImportFileSuffixTag>
{
static std::string Get(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent*)
{
if (target->HasImportLibrary(context->Config)) {
return target->GetFileSuffix(context->Config,
cmStateEnums::ImportLibraryArtifact);
}
return std::string{};
}
};
template <>
struct TargetFileArtifactResultGetter<ArtifactLinkerFileSuffixTag>
{
static std::string Get(cmGeneratorTarget* target,
@ -3260,9 +3527,10 @@ struct TargetFileArtifactResultGetter<ArtifactLinkerFileSuffixTag>
const GeneratorExpressionContent* content)
{
if (!target->IsLinkable()) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_LINKER_SUFFIX is allowed only for libraries and "
"executables with ENABLE_EXPORTS.");
::reportError(
context, content->GetOriginalExpression(),
"TARGET_LINKER_FILE_SUFFIX is allowed only for libraries and "
"executables with ENABLE_EXPORTS.");
return std::string();
}
@ -3274,6 +3542,51 @@ struct TargetFileArtifactResultGetter<ArtifactLinkerFileSuffixTag>
return target->GetFileSuffix(context->Config, artifact);
}
};
template <>
struct TargetFileArtifactResultGetter<ArtifactLinkerLibraryFileSuffixTag>
{
static std::string Get(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
if (!target->IsLinkable() ||
target->GetType() == cmStateEnums::STATIC_LIBRARY) {
::reportError(context, content->GetOriginalExpression(),
"TARGET_LINKER_LIBRARY_FILE_SUFFIX is allowed only for "
"libraries with ENABLE_EXPORTS.");
return std::string();
}
if (!target->IsDLLPlatform() ||
target->GetType() == cmStateEnums::STATIC_LIBRARY) {
return target->GetFileSuffix(context->Config,
cmStateEnums::RuntimeBinaryArtifact);
}
return std::string{};
}
};
template <>
struct TargetFileArtifactResultGetter<ArtifactLinkerImportFileSuffixTag>
{
static std::string Get(cmGeneratorTarget* target,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content)
{
if (!target->IsLinkable()) {
::reportError(
context, content->GetOriginalExpression(),
"TARGET_LINKER_IMPORT_FILE_SUFFIX is allowed only for libraries and "
"executables with ENABLE_EXPORTS.");
return std::string();
}
if (target->HasImportLibrary(context->Config)) {
return target->GetFileSuffix(context->Config,
cmStateEnums::ImportLibraryArtifact);
}
return std::string{};
}
};
template <typename ArtifactT>
struct TargetFileArtifact : public TargetArtifactBase
@ -3304,11 +3617,23 @@ struct TargetFileArtifact : public TargetArtifactBase
};
static const TargetFileArtifact<ArtifactFilePrefixTag> targetFilePrefixNode;
static const TargetFileArtifact<ArtifactImportFilePrefixTag>
targetImportFilePrefixNode;
static const TargetFileArtifact<ArtifactLinkerFilePrefixTag>
targetLinkerFilePrefixNode;
static const TargetFileArtifact<ArtifactLinkerLibraryFilePrefixTag>
targetLinkerLibraryFilePrefixNode;
static const TargetFileArtifact<ArtifactLinkerImportFilePrefixTag>
targetLinkerImportFilePrefixNode;
static const TargetFileArtifact<ArtifactFileSuffixTag> targetFileSuffixNode;
static const TargetFileArtifact<ArtifactImportFileSuffixTag>
targetImportFileSuffixNode;
static const TargetFileArtifact<ArtifactLinkerFileSuffixTag>
targetLinkerFileSuffixNode;
static const TargetFileArtifact<ArtifactLinkerLibraryFileSuffixTag>
targetLinkerLibraryFileSuffixNode;
static const TargetFileArtifact<ArtifactLinkerImportFileSuffixTag>
targetLinkerImportFileSuffixNode;
static const struct ShellPathNode : public cmGeneratorExpressionNode
{
@ -3376,23 +3701,52 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
{ "CONFIGURATION", &configurationNode },
{ "CONFIG", &configurationTestNode },
{ "TARGET_FILE", &targetNodeGroup.File },
{ "TARGET_IMPORT_FILE", &targetImportNodeGroup.File },
{ "TARGET_LINKER_FILE", &targetLinkerNodeGroup.File },
{ "TARGET_LINKER_LIBRARY_FILE", &targetLinkerLibraryNodeGroup.File },
{ "TARGET_LINKER_IMPORT_FILE", &targetLinkerImportNodeGroup.File },
{ "TARGET_SONAME_FILE", &targetSoNameNodeGroup.File },
{ "TARGET_SONAME_IMPORT_FILE", &targetSoNameImportNodeGroup.File },
{ "TARGET_PDB_FILE", &targetPdbNodeGroup.File },
{ "TARGET_FILE_BASE_NAME", &targetFileBaseNameNode },
{ "TARGET_IMPORT_FILE_BASE_NAME", &targetImportFileBaseNameNode },
{ "TARGET_LINKER_FILE_BASE_NAME", &targetLinkerFileBaseNameNode },
{ "TARGET_LINKER_LIBRARY_FILE_BASE_NAME",
&targetLinkerLibraryFileBaseNameNode },
{ "TARGET_LINKER_IMPORT_FILE_BASE_NAME",
&targetLinkerImportFileBaseNameNode },
{ "TARGET_PDB_FILE_BASE_NAME", &targetPdbFileBaseNameNode },
{ "TARGET_FILE_PREFIX", &targetFilePrefixNode },
{ "TARGET_IMPORT_FILE_PREFIX", &targetImportFilePrefixNode },
{ "TARGET_LINKER_FILE_PREFIX", &targetLinkerFilePrefixNode },
{ "TARGET_LINKER_LIBRARY_FILE_PREFIX",
&targetLinkerLibraryFilePrefixNode },
{ "TARGET_LINKER_IMPORT_FILE_PREFIX", &targetLinkerImportFilePrefixNode },
{ "TARGET_FILE_SUFFIX", &targetFileSuffixNode },
{ "TARGET_IMPORT_FILE_SUFFIX", &targetImportFileSuffixNode },
{ "TARGET_LINKER_FILE_SUFFIX", &targetLinkerFileSuffixNode },
{ "TARGET_LINKER_LIBRARY_FILE_SUFFIX",
&targetLinkerLibraryFileSuffixNode },
{ "TARGET_LINKER_IMPORT_FILE_SUFFIX", &targetLinkerImportFileSuffixNode },
{ "TARGET_FILE_NAME", &targetNodeGroup.FileName },
{ "TARGET_IMPORT_FILE_NAME", &targetImportNodeGroup.FileName },
{ "TARGET_LINKER_FILE_NAME", &targetLinkerNodeGroup.FileName },
{ "TARGET_LINKER_LIBRARY_FILE_NAME",
&targetLinkerLibraryNodeGroup.FileName },
{ "TARGET_LINKER_IMPORT_FILE_NAME",
&targetLinkerImportNodeGroup.FileName },
{ "TARGET_SONAME_FILE_NAME", &targetSoNameNodeGroup.FileName },
{ "TARGET_SONAME_IMPORT_FILE_NAME",
&targetSoNameImportNodeGroup.FileName },
{ "TARGET_PDB_FILE_NAME", &targetPdbNodeGroup.FileName },
{ "TARGET_FILE_DIR", &targetNodeGroup.FileDir },
{ "TARGET_IMPORT_FILE_DIR", &targetImportNodeGroup.FileDir },
{ "TARGET_LINKER_FILE_DIR", &targetLinkerNodeGroup.FileDir },
{ "TARGET_LINKER_LIBRARY_FILE_DIR",
&targetLinkerLibraryNodeGroup.FileDir },
{ "TARGET_LINKER_IMPORT_FILE_DIR", &targetLinkerImportNodeGroup.FileDir },
{ "TARGET_SONAME_FILE_DIR", &targetSoNameNodeGroup.FileDir },
{ "TARGET_SONAME_IMPORT_FILE_DIR", &targetSoNameImportNodeGroup.FileDir },
{ "TARGET_PDB_FILE_DIR", &targetPdbNodeGroup.FileDir },
{ "TARGET_BUNDLE_DIR", &targetBundleDirNode },
{ "TARGET_BUNDLE_DIR_NAME", &targetBundleDirNameNode },

View File

@ -458,6 +458,11 @@ std::string const& cmGeneratorTarget::GetSafeProperty(
const char* cmGeneratorTarget::GetOutputTargetType(
cmStateEnums::ArtifactType artifact) const
{
if (this->IsFrameworkOnApple() || this->GetGlobalGenerator()->IsXcode()) {
// import file (i.e. .tbd file) is always in same location as library
artifact = cmStateEnums::RuntimeBinaryArtifact;
}
switch (this->GetType()) {
case cmStateEnums::SHARED_LIBRARY:
if (this->IsDLLPlatform()) {
@ -470,9 +475,15 @@ const char* cmGeneratorTarget::GetOutputTargetType(
return "ARCHIVE";
}
} else {
// For non-DLL platforms shared libraries are treated as
// library targets.
return "LIBRARY";
switch (artifact) {
case cmStateEnums::RuntimeBinaryArtifact:
// For non-DLL platforms shared libraries are treated as
// library targets.
return "LIBRARY";
case cmStateEnums::ImportLibraryArtifact:
// Library import libraries are treated as archive targets.
return "ARCHIVE";
}
}
break;
case cmStateEnums::STATIC_LIBRARY:
@ -2518,7 +2529,8 @@ bool cmGeneratorTarget::CanGenerateInstallNameDir(
return !skip;
}
std::string cmGeneratorTarget::GetSOName(const std::string& config) const
std::string cmGeneratorTarget::GetSOName(
const std::string& config, cmStateEnums::ArtifactType artifact) const
{
if (this->IsImported()) {
// Lookup the imported soname.
@ -2546,7 +2558,9 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const
return "";
}
// Compute the soname that will be built.
return this->GetLibraryNames(config).SharedObject;
return artifact == cmStateEnums::RuntimeBinaryArtifact
? this->GetLibraryNames(config).SharedObject
: this->GetLibraryNames(config).ImportLibrary;
}
namespace {
@ -5088,10 +5102,18 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
f = cmStrCat(dir, '/', targetNames.PDB);
gg->AddToManifest(f);
}
dir = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
if (!targetNames.ImportOutput.empty()) {
f = cmStrCat(dir, '/', targetNames.ImportOutput);
gg->AddToManifest(f);
}
if (!targetNames.ImportLibrary.empty()) {
f =
cmStrCat(this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact),
'/', targetNames.ImportLibrary);
f = cmStrCat(dir, '/', targetNames.ImportLibrary);
gg->AddToManifest(f);
}
if (!targetNames.ImportReal.empty()) {
f = cmStrCat(dir, '/', targetNames.ImportReal);
gg->AddToManifest(f);
}
}
@ -5211,14 +5233,20 @@ std::string cmGeneratorTarget::NormalGetFullPath(
}
break;
case cmStateEnums::ImportLibraryArtifact:
fpath += this->GetFullName(config, cmStateEnums::ImportLibraryArtifact);
if (realname) {
fpath +=
this->NormalGetRealName(config, cmStateEnums::ImportLibraryArtifact);
} else {
fpath +=
this->GetFullName(config, cmStateEnums::ImportLibraryArtifact);
}
break;
}
return fpath;
}
std::string cmGeneratorTarget::NormalGetRealName(
const std::string& config) const
const std::string& config, cmStateEnums::ArtifactType artifact) const
{
// This should not be called for imported targets.
// TODO: Split cmTarget into a class hierarchy to get compile-time
@ -5229,12 +5257,13 @@ std::string cmGeneratorTarget::NormalGetRealName(
this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
}
if (this->GetType() == cmStateEnums::EXECUTABLE) {
// Compute the real name that will be built.
return this->GetExecutableNames(config).Real;
}
Names names = this->GetType() == cmStateEnums::EXECUTABLE
? this->GetExecutableNames(config)
: this->GetLibraryNames(config);
// Compute the real name that will be built.
return this->GetLibraryNames(config).Real;
return artifact == cmStateEnums::RuntimeBinaryArtifact ? names.Real
: names.ImportReal;
}
cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
@ -5279,17 +5308,16 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
// The library name.
targetNames.Base = components.base;
targetNames.Output =
components.prefix + targetNames.Base + components.suffix;
cmStrCat(components.prefix, targetNames.Base, components.suffix);
if (this->IsFrameworkOnApple()) {
targetNames.Real = components.prefix;
if (!this->Makefile->PlatformIsAppleEmbedded()) {
targetNames.Real += "Versions/";
targetNames.Real += this->GetFrameworkVersion();
targetNames.Real += "/";
targetNames.Real +=
cmStrCat("Versions/", this->GetFrameworkVersion(), '/');
}
targetNames.Real += targetNames.Base + components.suffix;
targetNames.SharedObject = targetNames.Real + components.suffix;
targetNames.Real += cmStrCat(targetNames.Base, components.suffix);
targetNames.SharedObject = targetNames.Real;
} else {
// The library's soname.
this->ComputeVersionedName(targetNames.SharedObject, components.prefix,
@ -5302,11 +5330,36 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
targetNames.Output, version);
}
// The import library name.
// The import library names.
if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GetType() == cmStateEnums::MODULE_LIBRARY) {
targetNames.ImportLibrary =
this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
NameComponents const& importComponents =
this->GetFullNameInternalComponents(config,
cmStateEnums::ImportLibraryArtifact);
targetNames.ImportOutput = cmStrCat(
importComponents.prefix, importComponents.base, importComponents.suffix);
if (this->IsFrameworkOnApple() && this->IsSharedLibraryWithExports()) {
targetNames.ImportReal = components.prefix;
if (!this->Makefile->PlatformIsAppleEmbedded()) {
targetNames.ImportReal +=
cmStrCat("Versions/", this->GetFrameworkVersion(), '/');
}
targetNames.ImportReal +=
cmStrCat(importComponents.base, importComponents.suffix);
targetNames.ImportLibrary = targetNames.ImportOutput;
} else {
// The import library's soname.
this->ComputeVersionedName(
targetNames.ImportLibrary, importComponents.prefix,
importComponents.base, importComponents.suffix,
targetNames.ImportOutput, soversion);
// The import library's real name on disk.
this->ComputeVersionedName(
targetNames.ImportReal, importComponents.prefix, importComponents.base,
importComponents.suffix, targetNames.ImportOutput, version);
}
}
// The program database file name.
@ -5368,6 +5421,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
// The import library name.
targetNames.ImportLibrary =
this->GetFullNameInternal(config, cmStateEnums::ImportLibraryArtifact);
targetNames.ImportReal = targetNames.ImportLibrary;
targetNames.ImportOutput = targetNames.ImportLibrary;
// The program database file name.
targetNames.PDB = this->GetPDBName(config);
@ -5449,15 +5504,18 @@ cmGeneratorTarget::GetFullNameInternalComponents(
}
// Compute the full name for main target types.
const std::string configPostfix = this->GetFilePostfix(config);
std::string configPostfix = this->GetFilePostfix(config);
// frameworks have directory prefix but no suffix
// frameworks have directory prefix
std::string fw_prefix;
if (this->IsFrameworkOnApple()) {
fw_prefix =
cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/');
targetPrefix = cmValue(fw_prefix);
targetSuffix = nullptr;
if (!isImportedLibraryArtifact) {
// no suffix
targetSuffix = nullptr;
}
}
if (this->IsCFBundleOnApple()) {
@ -5476,8 +5534,8 @@ cmGeneratorTarget::GetFullNameInternalComponents(
// When using Xcode, the postfix should be part of the suffix rather than
// the base, because the suffix ends up being used in Xcode's
// EXECUTABLE_SUFFIX attribute.
if (this->IsFrameworkOnApple() &&
this->GetGlobalGenerator()->GetName() == "Xcode") {
if (this->IsFrameworkOnApple() && this->GetGlobalGenerator()->IsXcode()) {
configPostfix += *targetSuffix;
targetSuffix = cmValue(configPostfix);
} else {
outBase += configPostfix;
@ -8544,15 +8602,35 @@ bool cmGeneratorTarget::IsExecutableWithExports() const
return this->Target->IsExecutableWithExports();
}
bool cmGeneratorTarget::IsSharedLibraryWithExports() const
{
return this->Target->IsSharedLibraryWithExports();
}
bool cmGeneratorTarget::HasImportLibrary(std::string const& config) const
{
bool generate_Stubs = true;
if (this->GetGlobalGenerator()->IsXcode()) {
// take care of CMAKE_XCODE_ATTRIBUTE_GENERATE_TEXT_BASED_STUBS variable
// as well as XCODE_ATTRIBUTE_GENERATE_TEXT_BASED_STUBS property
if (cmValue propGenStubs =
this->GetProperty("XCODE_ATTRIBUTE_GENERATE_TEXT_BASED_STUBS")) {
generate_Stubs = propGenStubs == "YES";
} else if (cmValue varGenStubs = this->Makefile->GetDefinition(
"CMAKE_XCODE_ATTRIBUTE_GENERATE_TEXT_BASED_STUBS")) {
generate_Stubs = varGenStubs == "YES";
}
}
return (this->IsDLLPlatform() &&
(this->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->IsExecutableWithExports()) &&
// Assemblies which have only managed code do not have
// import libraries.
this->GetManagedType(config) != ManagedType::Managed) ||
(this->IsAIX() && this->IsExecutableWithExports());
(this->IsAIX() && this->IsExecutableWithExports()) ||
(this->Makefile->PlatformSupportsAppleTextStubs() &&
this->IsSharedLibraryWithExports() && generate_Stubs);
}
bool cmGeneratorTarget::NeedImportLibraryName(std::string const& config) const

View File

@ -273,7 +273,9 @@ public:
std::string NormalGetFullPath(const std::string& config,
cmStateEnums::ArtifactType artifact,
bool realname) const;
std::string NormalGetRealName(const std::string& config) const;
std::string NormalGetRealName(const std::string& config,
cmStateEnums::ArtifactType artifact =
cmStateEnums::RuntimeBinaryArtifact) const;
/** Get the names of an object library's object files underneath
its object file directory. */
@ -348,7 +350,9 @@ public:
const std::string* GetExportMacro() const;
/** Get the soname of the target. Allowed only for a shared library. */
std::string GetSOName(const std::string& config) const;
std::string GetSOName(const std::string& config,
cmStateEnums::ArtifactType artifact =
cmStateEnums::RuntimeBinaryArtifact) const;
struct NameComponents
{
@ -740,6 +744,8 @@ public:
std::string Base;
std::string Output;
std::string Real;
std::string ImportOutput;
std::string ImportReal;
std::string ImportLibrary;
std::string PDB;
std::string SharedObject;
@ -786,6 +792,10 @@ public:
bool IsExecutableWithExports() const;
/* Return whether this target is a shared library with capability to generate
* a file describing symbols exported (for example, .tbd file on Apple). */
bool IsSharedLibraryWithExports() const;
/** Return whether or not the target has a DLL import library. */
bool HasImportLibrary(std::string const& config) const;

View File

@ -1270,6 +1270,10 @@ void cmGlobalNinjaGenerator::AppendTargetOutputs(
}
CM_FALLTHROUGH;
case cmStateEnums::EXECUTABLE: {
if (target->IsApple() && target->HasImportLibrary(config)) {
outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath(
config, cmStateEnums::ImportLibraryArtifact, realname)));
}
outputs.push_back(this->ConvertToNinjaPath(target->GetFullPath(
config, cmStateEnums::RuntimeBinaryArtifact, realname)));
break;

View File

@ -1739,7 +1739,7 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
std::string str_so_file =
cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>');
std::string str_link_file =
cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>');
cmStrCat("$<TARGET_LINKER_LIBRARY_FILE:", gtgt->GetName(), '>');
cmCustomCommandLines cmd = cmMakeSingleCommandLine(
{ cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library",
str_file, str_so_file, str_link_file });
@ -1754,6 +1754,27 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
postbuild.push_back(std::move(command));
}
if (gtgt->HasImportLibrary("") && !gtgt->IsFrameworkOnApple()) {
// create symbolic links for .tbd file
std::string file = cmStrCat("$<TARGET_IMPORT_FILE:", gtgt->GetName(), '>');
std::string soFile =
cmStrCat("$<TARGET_SONAME_IMPORT_FILE:", gtgt->GetName(), '>');
std::string linkFile =
cmStrCat("$<TARGET_LINKER_IMPORT_FILE:", gtgt->GetName(), '>');
cmCustomCommandLines symlink_command = cmMakeSingleCommandLine(
{ cmSystemTools::GetCMakeCommand(), "-E", "cmake_symlink_library", file,
soFile, linkFile });
cmCustomCommand command;
command.SetCommandLines(symlink_command);
command.SetComment("Creating import symlinks");
command.SetWorkingDirectory("");
command.SetBacktrace(this->CurrentMakefile->GetBacktrace());
command.SetStdPipesUTF8(true);
postbuild.push_back(std::move(command));
}
cmXCodeObject* legacyCustomCommandsBuildPhase = nullptr;
cmXCodeObject* preBuildPhase = nullptr;
cmXCodeObject* preLinkPhase = nullptr;
@ -2682,6 +2703,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
buildSettings->AddAttribute("LIBRARY_STYLE",
this->CreateString("DYNAMIC"));
if (gtgt->HasImportLibrary(configName)) {
// Request .tbd file generation
buildSettings->AddAttribute("GENERATE_TEXT_BASED_STUBS",
this->CreateString("YES"));
}
break;
}
case cmStateEnums::EXECUTABLE: {

View File

@ -553,34 +553,35 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
// Enforce argument rules too complex to specify for the
// general-purpose parser.
if (archiveArgs.GetNamelinkOnly() || runtimeArgs.GetNamelinkOnly() ||
objectArgs.GetNamelinkOnly() || frameworkArgs.GetNamelinkOnly() ||
bundleArgs.GetNamelinkOnly() || privateHeaderArgs.GetNamelinkOnly() ||
if (runtimeArgs.GetNamelinkOnly() || objectArgs.GetNamelinkOnly() ||
frameworkArgs.GetNamelinkOnly() || bundleArgs.GetNamelinkOnly() ||
privateHeaderArgs.GetNamelinkOnly() ||
publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
-> bool { return fileSetArg.GetNamelinkOnly(); }) ||
cxxModuleBmiArgs.GetNamelinkOnly()) {
status.SetError(
"TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
"The NAMELINK_ONLY option may be specified only following LIBRARY.");
"TARGETS given NAMELINK_ONLY option not in LIBRARY or ARCHIVE group. "
"The NAMELINK_ONLY option may be specified only following LIBRARY or "
"ARCHIVE.");
return false;
}
if (archiveArgs.GetNamelinkSkip() || runtimeArgs.GetNamelinkSkip() ||
objectArgs.GetNamelinkSkip() || frameworkArgs.GetNamelinkSkip() ||
bundleArgs.GetNamelinkSkip() || privateHeaderArgs.GetNamelinkSkip() ||
if (runtimeArgs.GetNamelinkSkip() || objectArgs.GetNamelinkSkip() ||
frameworkArgs.GetNamelinkSkip() || bundleArgs.GetNamelinkSkip() ||
privateHeaderArgs.GetNamelinkSkip() ||
publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip() ||
std::any_of(fileSetArgs.begin(), fileSetArgs.end(),
[](const cmInstallCommandFileSetArguments& fileSetArg)
-> bool { return fileSetArg.GetNamelinkSkip(); }) ||
cxxModuleBmiArgs.GetNamelinkSkip()) {
status.SetError(
"TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
"The NAMELINK_SKIP option may be specified only following LIBRARY.");
"TARGETS given NAMELINK_SKIP option not in LIBRARY or ARCHIVE group. "
"The NAMELINK_SKIP option may be specified only following LIBRARY or "
"ARCHIVE.");
return false;
}
if (archiveArgs.HasNamelinkComponent() ||
runtimeArgs.HasNamelinkComponent() ||
if (runtimeArgs.HasNamelinkComponent() ||
objectArgs.HasNamelinkComponent() ||
frameworkArgs.HasNamelinkComponent() ||
bundleArgs.HasNamelinkComponent() ||
@ -592,9 +593,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
-> bool { return fileSetArg.HasNamelinkComponent(); }) ||
cxxModuleBmiArgs.HasNamelinkComponent()) {
status.SetError(
"TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. "
"The NAMELINK_COMPONENT option may be specified only following "
"LIBRARY.");
"TARGETS given NAMELINK_COMPONENT option not in LIBRARY or ARCHIVE "
"group. The NAMELINK_COMPONENT option may be specified only following "
"LIBRARY or ARCHIVE.");
return false;
}
if (libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip()) {
@ -674,6 +675,14 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
} else if (libraryArgs.GetNamelinkSkip()) {
namelinkMode = cmInstallTargetGenerator::NamelinkModeSkip;
}
// Select the mode for installing symlinks to versioned imported libraries.
cmInstallTargetGenerator::NamelinkModeType importlinkMode =
cmInstallTargetGenerator::NamelinkModeNone;
if (archiveArgs.GetNamelinkOnly()) {
importlinkMode = cmInstallTargetGenerator::NamelinkModeOnly;
} else if (archiveArgs.GetNamelinkSkip()) {
importlinkMode = cmInstallTargetGenerator::NamelinkModeSkip;
}
// Check if there is something to do.
if (targetList.empty()) {
@ -725,6 +734,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
bool installsArchive = false;
bool installsLibrary = false;
bool installsNamelink = false;
bool installsImportlink = false;
bool installsRuntime = false;
bool installsObject = false;
bool installsFramework = false;
@ -742,6 +752,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
std::unique_ptr<cmInstallTargetGenerator> archiveGenerator;
std::unique_ptr<cmInstallTargetGenerator> libraryGenerator;
std::unique_ptr<cmInstallTargetGenerator> namelinkGenerator;
std::unique_ptr<cmInstallTargetGenerator> importlinkGenerator;
std::unique_ptr<cmInstallTargetGenerator> runtimeGenerator;
std::unique_ptr<cmInstallTargetGenerator> objectGenerator;
std::unique_ptr<cmInstallTargetGenerator> frameworkGenerator;
@ -885,6 +896,32 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
}
namelinkOnly =
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
if (target.GetMakefile()->PlatformSupportsAppleTextStubs() &&
target.IsSharedLibraryWithExports()) {
// Apple .tbd files use the ARCHIVE properties
if (!archiveArgs.GetDestination().empty()) {
artifactsSpecified = true;
}
if (importlinkMode !=
cmInstallTargetGenerator::NamelinkModeOnly) {
archiveGenerator = CreateInstallTargetGenerator(
target, archiveArgs, true, helper.Makefile->GetBacktrace(),
helper.GetLibraryDestination(&archiveArgs));
archiveGenerator->SetImportlinkMode(
cmInstallTargetGenerator::NamelinkModeSkip);
}
if (importlinkMode !=
cmInstallTargetGenerator::NamelinkModeSkip) {
importlinkGenerator = CreateInstallTargetGenerator(
target, archiveArgs, true, helper.Makefile->GetBacktrace(),
helper.GetLibraryDestination(&archiveArgs), false, true);
importlinkGenerator->SetImportlinkMode(
cmInstallTargetGenerator::NamelinkModeOnly);
}
namelinkOnly =
(importlinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
}
}
if (runtimeDependencySet && libraryGenerator) {
runtimeDependencySet->AddLibrary(libraryGenerator.get());
@ -1157,6 +1194,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
installsArchive = installsArchive || archiveGenerator;
installsLibrary = installsLibrary || libraryGenerator;
installsNamelink = installsNamelink || namelinkGenerator;
installsImportlink = installsImportlink || importlinkGenerator;
installsRuntime = installsRuntime || runtimeGenerator;
installsObject = installsObject || objectGenerator;
installsFramework = installsFramework || frameworkGenerator;
@ -1169,6 +1207,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
helper.Makefile->AddInstallGenerator(std::move(archiveGenerator));
helper.Makefile->AddInstallGenerator(std::move(libraryGenerator));
helper.Makefile->AddInstallGenerator(std::move(namelinkGenerator));
helper.Makefile->AddInstallGenerator(std::move(importlinkGenerator));
helper.Makefile->AddInstallGenerator(std::move(runtimeGenerator));
helper.Makefile->AddInstallGenerator(std::move(objectGenerator));
helper.Makefile->AddInstallGenerator(std::move(frameworkGenerator));
@ -1203,6 +1242,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
libraryArgs.GetNamelinkComponent());
}
if (installsImportlink) {
helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
archiveArgs.GetNamelinkComponent());
}
if (installsRuntime) {
helper.Makefile->GetGlobalGenerator()->AddInstallComponent(
runtimeArgs.GetComponent());

View File

@ -4,12 +4,15 @@
#include <algorithm>
#include <cassert>
#include <functional>
#include <map>
#include <set>
#include <sstream>
#include <utility>
#include <vector>
#include <cm/optional>
#include "cmComputeLinkInformation.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
@ -40,6 +43,84 @@ std::string computeInstallObjectDir(cmGeneratorTarget* gt,
objectDir += gt->GetName();
return objectDir;
}
void computeFilesToInstall(
cmInstallTargetGenerator::Files& files,
cmInstallTargetGenerator::NamelinkModeType namelinkMode,
std::string const& fromDirConfig, std::string const& output,
std::string const& library, std::string const& real,
cm::optional<std::function<void(std::string const&)>> GNUToMS = cm::nullopt)
{
bool haveNamelink = false;
auto convert = [&GNUToMS](std::string const& file) {
if (GNUToMS) {
(*GNUToMS)(file);
}
};
// Library link name.
std::string fromName = cmStrCat(fromDirConfig, output);
std::string toName = output;
// Library interface name.
std::string fromSOName;
std::string toSOName;
if (library != output) {
haveNamelink = true;
fromSOName = cmStrCat(fromDirConfig, library);
toSOName = library;
}
// Library implementation name.
std::string fromRealName;
std::string toRealName;
if (real != output && real != library) {
haveNamelink = true;
fromRealName = cmStrCat(fromDirConfig, real);
toRealName = real;
}
// Add the names based on the current namelink mode.
if (haveNamelink) {
files.NamelinkMode = namelinkMode;
// With a namelink we need to check the mode.
if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
// Install the namelink only.
files.From.emplace_back(fromName);
files.To.emplace_back(toName);
convert(output);
} else {
// Install the real file if it has its own name.
if (!fromRealName.empty()) {
files.From.emplace_back(fromRealName);
files.To.emplace_back(toRealName);
convert(real);
}
// Install the soname link if it has its own name.
if (!fromSOName.empty()) {
files.From.emplace_back(fromSOName);
files.To.emplace_back(toSOName);
convert(library);
}
// Install the namelink if it is not to be skipped.
if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
files.From.emplace_back(fromName);
files.To.emplace_back(toName);
convert(output);
}
}
} else {
// Without a namelink there will be only one file. Install it
// if this is not a namelink-only rule.
if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
files.From.emplace_back(fromName);
files.To.emplace_back(toName);
convert(output);
}
}
}
}
cmInstallTargetGenerator::cmInstallTargetGenerator(
@ -56,6 +137,7 @@ cmInstallTargetGenerator::cmInstallTargetGenerator(
{
this->ActionsPerConfig = true;
this->NamelinkMode = NamelinkModeNone;
this->ImportlinkMode = NamelinkModeNone;
}
cmInstallTargetGenerator::~cmInstallTargetGenerator() = default;
@ -247,18 +329,21 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
this->Target->GetLibraryNames(config);
if (this->ImportLibrary) {
// There is a bug in cmInstallCommand if this fails.
assert(this->NamelinkMode == NamelinkModeNone);
assert(this->Target->Makefile->PlatformSupportsAppleTextStubs() ||
this->ImportlinkMode == NamelinkModeNone);
std::string from1 = fromDirConfig + targetNames.ImportLibrary;
std::string to1 = targetNames.ImportLibrary;
files.From.emplace_back(std::move(from1));
files.To.emplace_back(std::move(to1));
std::string targetNameImportLib;
if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
targetNameImportLib)) {
files.From.emplace_back(fromDirConfig + targetNameImportLib);
files.To.emplace_back(targetNameImportLib);
}
auto GNUToMS = [this, &config, &files,
&fromDirConfig](const std::string& lib) {
std::string importLib;
if (this->Target->GetImplibGNUtoMS(config, lib, importLib)) {
files.From.emplace_back(fromDirConfig + importLib);
files.To.emplace_back(importLib);
}
};
computeFilesToInstall(
files, this->ImportlinkMode, fromDirConfig, targetNames.ImportOutput,
targetNames.ImportLibrary, targetNames.ImportReal, GNUToMS);
// An import library looks like a static library.
files.Type = cmInstallType_STATIC_LIBRARY;
@ -318,66 +403,9 @@ cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
files.From.emplace_back(std::move(from1));
files.To.emplace_back(std::move(to1));
} else {
bool haveNamelink = false;
// Library link name.
std::string fromName = fromDirConfig + targetNames.Output;
std::string toName = targetNames.Output;
// Library interface name.
std::string fromSOName;
std::string toSOName;
if (targetNames.SharedObject != targetNames.Output) {
haveNamelink = true;
fromSOName = fromDirConfig + targetNames.SharedObject;
toSOName = targetNames.SharedObject;
}
// Library implementation name.
std::string fromRealName;
std::string toRealName;
if (targetNames.Real != targetNames.Output &&
targetNames.Real != targetNames.SharedObject) {
haveNamelink = true;
fromRealName = fromDirConfig + targetNames.Real;
toRealName = targetNames.Real;
}
// Add the names based on the current namelink mode.
if (haveNamelink) {
files.NamelinkMode = this->NamelinkMode;
// With a namelink we need to check the mode.
if (this->NamelinkMode == NamelinkModeOnly) {
// Install the namelink only.
files.From.emplace_back(fromName);
files.To.emplace_back(toName);
} else {
// Install the real file if it has its own name.
if (!fromRealName.empty()) {
files.From.emplace_back(fromRealName);
files.To.emplace_back(toRealName);
}
// Install the soname link if it has its own name.
if (!fromSOName.empty()) {
files.From.emplace_back(fromSOName);
files.To.emplace_back(toSOName);
}
// Install the namelink if it is not to be skipped.
if (this->NamelinkMode != NamelinkModeSkip) {
files.From.emplace_back(fromName);
files.To.emplace_back(toName);
}
}
} else {
// Without a namelink there will be only one file. Install it
// if this is not a namelink-only rule.
if (this->NamelinkMode != NamelinkModeOnly) {
files.From.emplace_back(fromName);
files.To.emplace_back(toName);
}
}
computeFilesToInstall(files, this->NamelinkMode, fromDirConfig,
targetNames.Output, targetNames.SharedObject,
targetNames.Real);
}
}
@ -425,6 +453,12 @@ std::string cmInstallTargetGenerator::GetInstallFilename(
"${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
fname = targetNames.ImportLibrary;
}
} else if (nameType == NameImplibReal) {
// Use the import library name.
if (!target->GetImplibGNUtoMS(config, targetNames.ImportReal, fname,
"${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
fname = targetNames.ImportReal;
}
} else if (nameType == NameReal) {
// Use the canonical name.
fname = targetNames.Real;
@ -434,11 +468,14 @@ std::string cmInstallTargetGenerator::GetInstallFilename(
}
} else {
cmGeneratorTarget::Names targetNames = target->GetLibraryNames(config);
if (nameType == NameImplib) {
if (nameType == NameImplib || nameType == NameImplibReal) {
const auto& importName = nameType == NameImplib
? targetNames.ImportLibrary
: targetNames.ImportReal;
// Use the import library name.
if (!target->GetImplibGNUtoMS(config, targetNames.ImportLibrary, fname,
if (!target->GetImplibGNUtoMS(config, importName, fname,
"${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
fname = targetNames.ImportLibrary;
fname = importName;
}
} else if (nameType == NameSO) {
// Use the soname.

View File

@ -39,6 +39,10 @@ public:
NamelinkModeSkip
};
void SetNamelinkMode(NamelinkModeType mode) { this->NamelinkMode = mode; }
void SetImportlinkMode(NamelinkModeType mode)
{
this->ImportlinkMode = mode;
}
std::string GetInstallFilename(const std::string& config) const;
@ -50,7 +54,8 @@ public:
NameNormal,
NameImplib,
NameSO,
NameReal
NameReal,
NameImplibReal
};
static std::string GetInstallFilename(const cmGeneratorTarget* target,
@ -121,6 +126,7 @@ protected:
cmGeneratorTarget* Target = nullptr;
std::string const FilePermissions;
NamelinkModeType NamelinkMode;
NamelinkModeType ImportlinkMode;
bool const ImportLibrary;
bool const Optional;
};

View File

@ -85,6 +85,7 @@ static auto ruleReplaceVars = { "CMAKE_${LANG}_COMPILER",
"CMAKE_RANLIB",
"CMAKE_LINKER",
"CMAKE_MT",
"CMAKE_TAPI",
"CMAKE_CUDA_HOST_COMPILER",
"CMAKE_CUDA_HOST_LINK_LAUNCHER",
"CMAKE_CL_SHOWINCLUDES_PREFIX" };
@ -134,6 +135,13 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
this->LinkerSysroot = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
}
// OSX SYSROOT can be required by some tools, like tapi
{
cmValue osxSysroot = this->Makefile->GetDefinition("CMAKE_OSX_SYSROOT");
this->VariableMappings["CMAKE_OSX_SYSROOT"] =
osxSysroot.IsEmpty() ? "/" : this->EscapeForShell(*osxSysroot, true);
}
if (cmValue appleArchSysroots =
this->Makefile->GetDefinition("CMAKE_APPLE_ARCH_SYSROOTS")) {
std::string const& appleArchs =

View File

@ -2493,6 +2493,11 @@ bool cmMakefile::PlatformIsAppleEmbedded() const
return this->GetAppleSDKType() != AppleSDK::MacOS;
}
bool cmMakefile::PlatformSupportsAppleTextStubs() const
{
return this->IsOn("APPLE") && this->IsSet("CMAKE_TAPI");
}
const char* cmMakefile::GetSONameFlag(const std::string& language) const
{
std::string name = "CMAKE_SHARED_LIBRARY_SONAME";

View File

@ -562,6 +562,10 @@ public:
/** Return whether the target platform is Apple iOS. */
bool PlatformIsAppleEmbedded() const;
/** Return whether the target platform supports generation of text base stubs
(.tbd file) describing exports (Apple specific). */
bool PlatformSupportsAppleTextStubs() const;
/** Retrieve soname flag for the specified language if supported */
const char* GetSONameFlag(const std::string& language) const;

View File

@ -465,9 +465,20 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
std::string outpathImp;
if (this->GeneratorTarget->IsFrameworkOnApple()) {
outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName());
cmOSXBundleGenerator::SkipParts bundleSkipParts;
if (this->GeneratorTarget->HasImportLibrary(this->GetConfigName())) {
bundleSkipParts.TextStubs = false;
}
this->OSXBundleGenerator->CreateFramework(this->TargetNames.Output,
outpath, this->GetConfigName());
outpath, this->GetConfigName(),
bundleSkipParts);
outpath += '/';
if (!this->TargetNames.ImportLibrary.empty()) {
outpathImp = this->GeneratorTarget->GetDirectory(
this->GetConfigName(), cmStateEnums::ImportLibraryArtifact);
cmSystemTools::MakeDirectory(outpathImp);
outpathImp += '/';
}
} else if (this->GeneratorTarget->IsCFBundleOnApple()) {
outpath = this->GeneratorTarget->GetDirectory(this->GetConfigName());
this->OSXBundleGenerator->CreateCFBundle(this->TargetNames.Output, outpath,
@ -679,11 +690,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
}
// Expand the rule variables.
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->LocalGenerator->CreateRulePlaceholderExpander());
bool useWatcomQuote =
this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE");
std::vector<std::string> real_link_commands;
{
bool useWatcomQuote =
this->Makefile->IsOn(linkRuleVar + "_USE_WATCOM_QUOTE");
// Set path conversion for link script shells.
this->LocalGenerator->SetLinkScriptShell(useLinkScript);
@ -816,8 +828,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
launcher = cmStrCat(val, ' ');
}
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->LocalGenerator->CreateRulePlaceholderExpander());
// Construct the main link rule and expand placeholders.
rulePlaceholderExpander->SetTargetImpLib(targetOutPathImport);
if (useArchiveRules) {
@ -950,6 +960,86 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends,
commands, false);
// Add rule to generate text-based stubs, if required
if (this->GeneratorTarget->IsApple() &&
this->GeneratorTarget->HasImportLibrary(this->GetConfigName())) {
auto genStubsRule =
this->Makefile->GetDefinition("CMAKE_CREATE_TEXT_STUBS");
auto genStubs_commands = cmExpandedList(genStubsRule);
std::string TBDFullPath =
cmStrCat(outpathImp, this->TargetNames.ImportOutput);
std::string TBDFullPathReal =
cmStrCat(outpathImp, this->TargetNames.ImportReal);
std::string TBDFullPathSO =
cmStrCat(outpathImp, this->TargetNames.ImportLibrary);
// Expand placeholders.
cmRulePlaceholderExpander::RuleVariables vars;
std::string target = this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->MaybeRelativeToCurBinDir(targetFullPathReal),
cmOutputConverter::SHELL, useWatcomQuote);
vars.Target = target.c_str();
std::string TBDOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->MaybeRelativeToCurBinDir(TBDFullPathReal),
cmOutputConverter::SHELL, useWatcomQuote);
rulePlaceholderExpander->SetTargetImpLib(TBDOutPathReal);
for (std::string& command : genStubs_commands) {
rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
command, vars);
}
outputs.clear();
outputs.push_back(TBDFullPathReal);
if (this->TargetNames.ImportLibrary != this->TargetNames.ImportReal) {
outputs.push_back(TBDFullPathSO);
}
if (this->TargetNames.ImportOutput != this->TargetNames.ImportLibrary &&
this->TargetNames.ImportOutput != this->TargetNames.ImportReal) {
outputs.push_back(TBDFullPath);
}
this->ExtraFiles.insert(TBDFullPath);
depends.clear();
depends.push_back(targetFullPathReal);
// Add a rule to create necessary symlinks for the library.
// Frameworks are handled by cmOSXBundleGenerator.
if (TBDFullPath != TBDFullPathReal &&
!this->GeneratorTarget->IsFrameworkOnApple()) {
auto TBDOutPathSO = this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->MaybeRelativeToCurBinDir(TBDFullPathSO),
cmOutputConverter::SHELL, useWatcomQuote);
auto TBDOutPath = this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->MaybeRelativeToCurBinDir(TBDFullPath),
cmOutputConverter::SHELL, useWatcomQuote);
std::string symlink =
cmStrCat("$(CMAKE_COMMAND) -E cmake_symlink_library ", TBDOutPathReal,
' ', TBDOutPathSO, ' ', TBDOutPath);
commands1.push_back(std::move(symlink));
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
cm::append(genStubs_commands, commands1);
commands1.clear();
}
this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends,
genStubs_commands, false);
// clean actions for apple specific outputs
// clean actions for ImportLibrary are already specified
if (this->TargetNames.ImportReal != this->TargetNames.ImportLibrary) {
libCleanFiles.insert(
this->LocalGenerator->MaybeRelativeToCurBinDir(TBDFullPathReal));
}
if (this->TargetNames.ImportOutput != this->TargetNames.ImportReal &&
this->TargetNames.ImportOutput != this->TargetNames.ImportLibrary) {
libCleanFiles.insert(
this->LocalGenerator->MaybeRelativeToCurBinDir(TBDFullPath));
}
}
// Write the main driver rule to build everything in this target.
this->WriteTargetDriverRule(targetFullPath, relink);

View File

@ -204,6 +204,15 @@ std::string cmNinjaNormalTargetGenerator::LanguageLinkerCudaFatbinaryRule(
'_', config);
}
std::string cmNinjaNormalTargetGenerator::TextStubsGeneratorRule(
const std::string& config) const
{
return cmStrCat(
"TEXT_STUBS_GENERATOR__",
cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()),
'_', config);
}
struct cmNinjaRemoveNoOpCommands
{
bool operator()(std::string const& cmd)
@ -527,6 +536,45 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
this->GetGlobalGenerator()->AddRule(rule);
}
}
if (this->GetGeneratorTarget()->IsApple() &&
this->GetGeneratorTarget()->HasImportLibrary(config)) {
cmNinjaRule rule(this->TextStubsGeneratorRule(config));
rule.Comment = cmStrCat("Rule for generating text-based stubs for ",
this->GetVisibleTypeName(), '.');
rule.Description = "Creating text-based stubs $out";
std::string cmd =
this->GetMakefile()->GetDefinition("CMAKE_CREATE_TEXT_STUBS");
std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
this->GetLocalGenerator()->CreateRulePlaceholderExpander());
cmRulePlaceholderExpander::RuleVariables vars;
vars.Target = "$in";
rulePlaceholderExpander->SetTargetImpLib("$out");
rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
cmd, vars);
rule.Command =
this->GetLocalGenerator()->BuildCommandLine({ cmd }, config, config);
this->GetGlobalGenerator()->AddRule(rule);
if (tgtNames.ImportOutput != tgtNames.ImportReal &&
!this->GetGeneratorTarget()->IsFrameworkOnApple()) {
cmNinjaRule slRule("CMAKE_SYMLINK_IMPORT_LIBRARY");
{
std::string cmakeCommand =
this->GetLocalGenerator()->ConvertToOutputFormat(
cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
std::string slCmd =
cmStrCat(cmakeCommand, " -E cmake_symlink_library $in $SONAME $out");
slRule.Command = this->GetLocalGenerator()->BuildCommandLine(
{ slCmd }, config, config);
}
slRule.Description = "Creating import library symlink $out";
slRule.Comment = "Rule for creating import library symlink.";
this->GetGlobalGenerator()->AddRule(slRule);
}
}
}
std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd()
@ -1030,9 +1078,12 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
// the current configuration has a postfix. The non-postfix configuration
// Info.plist can be used by all the other configurations.
if (!postFix.empty()) {
bundleSkipParts.infoPlist = true;
bundleSkipParts.InfoPlist = true;
}
}
if (gt->HasImportLibrary(config)) {
bundleSkipParts.TextStubs = false;
}
this->OSXBundleGenerator->CreateFramework(
tgtNames.Output, gt->GetDirectory(config), config, bundleSkipParts);
@ -1214,7 +1265,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
cmGlobalNinjaGenerator::CCOutputs byproducts(this->GetGlobalGenerator());
if (!tgtNames.ImportLibrary.empty()) {
if (!gt->IsApple() && !tgtNames.ImportLibrary.empty()) {
const std::string impLibPath = localGen.ConvertToOutputFormat(
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
@ -1471,6 +1522,55 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
// Add aliases for the file name and the target name.
globalGen->AddTargetAlias(tgtNames.Output, gt, config);
globalGen->AddTargetAlias(this->GetTargetName(), gt, config);
if (this->GetGeneratorTarget()->IsApple() &&
this->GetGeneratorTarget()->HasImportLibrary(config)) {
auto dirTBD =
gt->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
auto targetTBD =
this->ConvertToNinjaPath(cmStrCat(dirTBD, '/', tgtNames.ImportReal));
this->EnsureParentDirectoryExists(targetTBD);
cmNinjaBuild build(this->TextStubsGeneratorRule(config));
build.Comment = cmStrCat("Generate the text-based stubs file ", targetTBD);
build.Outputs.push_back(targetTBD);
build.ExplicitDeps.push_back(targetOutputReal);
globalGen->WriteBuild(this->GetImplFileStream(fileConfig), build);
if (tgtNames.ImportOutput != tgtNames.ImportReal &&
!this->GetGeneratorTarget()->IsFrameworkOnApple()) {
auto outputTBD =
this->ConvertToNinjaPath(cmStrCat(dirTBD, '/', tgtNames.ImportOutput));
std::string const soNameTBD = this->ConvertToNinjaPath(
cmStrCat(dirTBD, '/', tgtNames.ImportLibrary));
cmNinjaBuild slBuild("CMAKE_SYMLINK_IMPORT_LIBRARY");
slBuild.Comment = cmStrCat("Create import library symlink ", outputTBD);
cmNinjaVars slVars;
// If one link has to be created.
if (targetTBD == soNameTBD || outputTBD == soNameTBD) {
slVars["SONAME"] = this->GetLocalGenerator()->ConvertToOutputFormat(
soNameTBD, cmOutputConverter::SHELL);
} else {
slVars["SONAME"].clear();
slBuild.Outputs.push_back(soNameTBD);
if (firstForConfig) {
globalGen->GetByproductsForCleanTarget(config).push_back(soNameTBD);
}
}
slBuild.Outputs.push_back(outputTBD);
if (firstForConfig) {
globalGen->GetByproductsForCleanTarget(config).push_back(outputTBD);
}
slBuild.ExplicitDeps.push_back(targetTBD);
slBuild.Variables = std::move(slVars);
globalGen->WriteBuild(this->GetImplFileStream(fileConfig), slBuild);
}
// Add alias for the import file name
globalGen->AddTargetAlias(tgtNames.ImportOutput, gt, config);
}
}
void cmNinjaNormalTargetGenerator::WriteObjectLibStatement(

View File

@ -25,6 +25,7 @@ private:
std::string LanguageLinkerCudaDeviceCompileRule(
const std::string& config) const;
std::string LanguageLinkerCudaFatbinaryRule(const std::string& config) const;
std::string TextStubsGeneratorRule(const std::string& config) const;
const char* GetVisibleTypeName() const;
void WriteLanguagesRules(const std::string& config);

View File

@ -11,6 +11,7 @@
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"
class cmSourceFile;
@ -77,7 +78,7 @@ void cmOSXBundleGenerator::CreateFramework(
std::string frameworkVersion = this->GT->GetFrameworkVersion();
std::string name = cmSystemTools::GetFilenameName(targetName);
if (!skipParts.infoPlist) {
if (!skipParts.InfoPlist) {
// Configure the Info.plist file
std::string plist = newoutpath;
if (!this->Makefile->PlatformIsAppleEmbedded()) {
@ -120,6 +121,17 @@ void cmOSXBundleGenerator::CreateFramework(
cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
if (!skipParts.TextStubs) {
// foo.tbd -> Versions/Current/foo.tbd
cmValue tbdSuffix =
this->Makefile->GetDefinition("CMAKE_APPLE_IMPORT_FILE_SUFFIX");
oldName = cmStrCat("Versions/Current/", name, tbdSuffix);
newName = cmStrCat(contentdir, name, tbdSuffix);
cmSystemTools::RemoveFile(newName);
cmSystemTools::CreateSymlink(oldName, newName);
this->Makefile->AddCMakeOutputFile(newName);
}
// Resources -> Versions/Current/Resources
if (this->MacContentFolders->find("Resources") !=
this->MacContentFolders->end()) {

View File

@ -20,11 +20,10 @@ public:
struct SkipParts
{
SkipParts()
: infoPlist(false)
{
}
bool infoPlist; // NOLINT(modernize-use-default-member-init)
SkipParts() {} // NOLINT(modernize-use-equals-default)
bool InfoPlist = false;
bool TextStubs = true;
};
// create an app bundle at a given root, and return
@ -35,7 +34,7 @@ public:
// create a framework at a given root
void CreateFramework(const std::string& targetName, const std::string& root,
const std::string& config,
const SkipParts& skipParts = SkipParts());
const SkipParts& skipParts = SkipParts{});
// create a cf bundle at a given root
void CreateCFBundle(const std::string& targetName, const std::string& root,

View File

@ -445,7 +445,7 @@ TargetProperty const StaticTargetProperties[] = {
{ "AUTORCC_OPTIONS"_s, IC::CanCompileSources },
// Linking properties
{ "ENABLE_EXPORTS"_s, IC::ExecutableTarget },
{ "ENABLE_EXPORTS"_s, IC::TargetWithSymbolExports },
{ "LINK_LIBRARIES_ONLY_TARGETS"_s, IC::NormalNonImportedTarget },
{ "LINK_SEARCH_START_STATIC"_s, IC::CanCompileSources },
{ "LINK_SEARCH_END_STATIC"_s, IC::CanCompileSources },
@ -1031,6 +1031,31 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
defKey += "CMAKE_";
auto initProperty = [this, mf, &defKey](const std::string& property,
const char* default_value) {
// special init for ENABLE_EXPORTS
// For SHARED_LIBRARY, only CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS variable
// is used
// For EXECUTABLE, CMAKE_EXECUTABLE_ENABLE_EXPORTS or else
// CMAKE_ENABLE_EXPORTS variables are used
if (property == "ENABLE_EXPORTS"_s) {
// Replace everything after "CMAKE_"
defKey.replace(
defKey.begin() + 6, defKey.end(),
cmStrCat(this->impl->TargetType == cmStateEnums::EXECUTABLE
? "EXECUTABLE"
: "SHARED_LIBRARY",
'_', property));
if (cmValue value = mf->GetDefinition(defKey)) {
this->SetProperty(property, value);
return;
}
if (this->impl->TargetType == cmStateEnums::SHARED_LIBRARY) {
if (default_value) {
this->SetProperty(property, default_value);
}
return;
}
}
// Replace everything after "CMAKE_"
defKey.replace(defKey.begin() + 6, defKey.end(), property);
if (cmValue value = mf->GetDefinition(defKey)) {
@ -1205,6 +1230,12 @@ bool cmTarget::IsExecutableWithExports() const
this->GetPropertyAsBool("ENABLE_EXPORTS"));
}
bool cmTarget::IsSharedLibraryWithExports() const
{
return (this->GetType() == cmStateEnums::SHARED_LIBRARY &&
this->GetPropertyAsBool("ENABLE_EXPORTS"));
}
bool cmTarget::IsFrameworkOnApple() const
{
return ((this->GetType() == cmStateEnums::SHARED_LIBRARY ||
@ -2657,7 +2688,8 @@ const char* cmTarget::GetSuffixVariableInternal(
case cmStateEnums::RuntimeBinaryArtifact:
return "CMAKE_SHARED_LIBRARY_SUFFIX";
case cmStateEnums::ImportLibraryArtifact:
return "CMAKE_IMPORT_LIBRARY_SUFFIX";
return this->IsApple() ? "CMAKE_APPLE_IMPORT_FILE_SUFFIX"
: "CMAKE_IMPORT_LIBRARY_SUFFIX";
}
break;
case cmStateEnums::MODULE_LIBRARY:
@ -2698,7 +2730,8 @@ const char* cmTarget::GetPrefixVariableInternal(
case cmStateEnums::RuntimeBinaryArtifact:
return "CMAKE_SHARED_LIBRARY_PREFIX";
case cmStateEnums::ImportLibraryArtifact:
return "CMAKE_IMPORT_LIBRARY_PREFIX";
return this->IsApple() ? "CMAKE_APPLE_IMPORT_FILE_PREFIX"
: "CMAKE_IMPORT_LIBRARY_PREFIX";
}
break;
case cmStateEnums::MODULE_LIBRARY:

View File

@ -221,6 +221,10 @@ public:
//! Return whether this target is an executable with symbol exports enabled.
bool IsExecutableWithExports() const;
//! Return whether this target is a shared library with symbol exports
//! enabled.
bool IsSharedLibraryWithExports() const;
//! Return whether this target is a shared library Framework on Apple.
bool IsFrameworkOnApple() const;

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.5)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,12 @@
enable_language(C)
add_library(foo SHARED foo.c)
set_property(TARGET foo PROPERTY FRAMEWORK TRUE)
set_property(TARGET foo PROPERTY ENABLE_EXPORTS TRUE)
set_property(TARGET foo PROPERTY LIBRARY_OUTPUT_DIRECTORY $<CONFIG>)
install(TARGETS foo EXPORT foo FRAMEWORK DESTINATION DESTINATION "${CMAKE_BINARY_DIR}/$<CONFIG>")
install(EXPORT foo DESTINATION lib/foo NAMESPACE foo-install::)
install(FILES foo-config.cmake.in RENAME foo-config.cmake DESTINATION lib/foo)
export(TARGETS foo NAMESPACE foo-build:: FILE Release/foo.cmake)

View File

@ -0,0 +1,62 @@
enable_language(C)
find_package(foo REQUIRED CONFIG NO_DEFAULT_PATH)
add_executable(main main.c)
target_link_libraries(main PRIVATE foo-install::foo)
get_property(is_framework TARGET foo-install::foo PROPERTY FRAMEWORK)
if (NOT is_framework)
message(SEND_ERROR "foo-build::foo: FRAMEWORK not set.")
endif()
get_property(enable_exports TARGET foo-install::foo PROPERTY ENABLE_EXPORTS)
if (CAMKE_TAPI AND NOT enable_exports)
message(SEND_ERROR "foo-install::foo: ENABLE_EXPORTS not set.")
endif()
get_property(implib TARGET foo-install::foo PROPERTY IMPORTED_IMPLIB_RELEASE)
if (CAMKE_TAPI AND NOT implib)
message(SEND_ERROR "foo-install::foo: IMPORTED_IMPLIB_RELEASE not set.")
endif()
if (CAMKE_TAPI AND NOT implib MATCHES "foo.framework/Versions/A/foo.tbd$")
message(SEND_ERROR "foo-install::foo: ${implib}: wrong value for IMPORTED_IMPLIB_RELEASE.")
endif()
get_property(location TARGET foo-install::foo PROPERTY IMPORTED_LOCATION_RELEASE)
if (NOT location)
message(SEND_ERROR "foo-install::foo: IMPORTED_LOCATION_RELEASE not set.")
endif()
if (NOT location MATCHES "foo.framework/Versions/A/foo$")
message(SEND_ERROR "foo-install::foo: ${location}: wrong value for IMPORTED_LOCATION_RELEASE.")
endif()
include(${foo_BUILD}/foo.cmake)
add_executable(main2 main.c)
target_link_libraries(main2 PRIVATE foo-build::foo)
get_property(is_framework TARGET foo-build::foo PROPERTY FRAMEWORK)
if (NOT is_framework)
message(SEND_ERROR "foo-build::foo: FRAMEWORK not set.")
endif()
get_property(enable_exports TARGET foo-build::foo PROPERTY ENABLE_EXPORTS)
if (CAMKE_TAPI AND NOT enable_exports)
message(SEND_ERROR "foo-build::foo: ENABLE_EXPORTS not set.")
endif()
get_property(implib TARGET foo-build::foo PROPERTY IMPORTED_IMPLIB_RELEASE)
if (CAMKE_TAPI AND NOT implib)
message(SEND_ERROR "foo-build::foo: IMPORTED_IMPLIB_RELEASE not set.")
endif()
if (CAMKE_TAPI AND NOT implib STREQUAL "${foo_BUILD}/foo.framework/Versions/A/foo.tbd")
message(SEND_ERROR "foo-build::foo: ${implib}: wrong value for IMPORTED_IMPLIB_RELEASE.")
endif()
get_property(location TARGET foo-build::foo PROPERTY IMPORTED_LOCATION_RELEASE)
if (NOT location)
message(SEND_ERROR "foo-build::foo: IMPORTED_LOCATION_RELEASE not set.")
endif()
if (NOT location STREQUAL "${foo_BUILD}/foo.framework/Versions/A/foo")
message(SEND_ERROR "foo-build::foo: ${location}: wrong value for IMPORTED_LOCATION_RELEASE.")
endif()

View File

@ -0,0 +1 @@
include ("${RunCMake_TEST_BINARY_DIR}/Framework-Release-generated.cmake")

View File

@ -0,0 +1,59 @@
enable_language(C)
add_library(foo SHARED foo.c)
set_property(TARGET foo PROPERTY ENABLE_EXPORTS TRUE)
set_property(TARGET foo PROPERTY FRAMEWORK TRUE)
add_executable(main main.c)
target_link_libraries(main PRIVATE foo)
install(TARGETS foo FRAMEWORK DESTINATION "${CMAKE_BINARY_DIR}/INSTALL")
# LIBRARY and ARCHIVE should be ignored
install(TARGETS foo FRAMEWORK DESTINATION "${CMAKE_BINARY_DIR}/INSTALL2"
LIBRARY DESTINATION "${CMAKE_BINARY_DIR}/INSTALL2/lib"
ARCHIVE DESTINATION "${CMAKE_BINARY_DIR}/INSTALL2/dev")
set (GENERATE_CONTENT "if (\"${CMAKE_TAPI}\")
set (APPLE_TEXT_STUBS_SUPPORTED TRUE)
endif()\n\n")
string (APPEND GENERATE_CONTENT [[
macro (CHECK_FILE test_msg path)
if (NOT EXISTS "${path}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${path}\" not found\n")
endif()
endmacro()
macro (CHECK_SYMLINK test_msg path)
if(NOT IS_SYMLINK "${path}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${path}\" is not a symbolic link\n")
elseif (NOT EXISTS "${path}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${path}\" is not a valid symlink\n")
endif()
endmacro()
check_file("DYLIB file" "$<TARGET_FILE:foo>")
check_symlink("Public DYLIB file" "$<TARGET_LINKER_LIBRARY_FILE:foo>")
check_file("executable file" "$<TARGET_FILE:main>")
check_file("Installed DYLIB file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/foo.framework/Versions/A/$<TARGET_FILE_NAME:foo>")
check_symlink("Installed Public DULIB file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/foo.framework/$<TARGET_FILE_NAME:foo>")
check_file("Installed DULIB file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/foo.framework/Versions/A/$<TARGET_FILE_NAME:foo>")
check_symlink("Installed Public DYLIB file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/foo.framework/$<TARGET_FILE_NAME:foo>")
if (APPLE_TEXT_STUBS_SUPPORTED)
check_file("TBD file" "$<TARGET_IMPORT_FILE:foo>")
check_symlink("Public TBD file" "$<TARGET_LINKER_IMPORT_FILE:foo>")
check_file("Installed TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/foo.framework/Versions/A/$<TARGET_IMPORT_FILE_NAME:foo>")
check_symlink("Installed Public TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/foo.framework/$<TARGET_IMPORT_FILE_NAME:foo>")
check_file("Installed TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/foo.framework/Versions/A/$<TARGET_IMPORT_FILE_NAME:foo>")
check_symlink("Installed Public TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/foo.framework/$<TARGET_IMPORT_FILE_NAME:foo>")
endif()
]])
file (GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Framework-$<CONFIG>-generated.cmake"
CONTENT "${GENERATE_CONTENT}")

View File

@ -0,0 +1,12 @@
enable_language(C)
add_library(foo SHARED foo.c)
set_property(TARGET foo PROPERTY ENABLE_EXPORTS TRUE)
set_property(TARGET foo PROPERTY LIBRARY_OUTPUT_DIRECTORY $<CONFIG>)
set_property(TARGET foo PROPERTY ARCHIVE_OUTPUT_DIRECTORY $<CONFIG>)
install(TARGETS foo EXPORT foo DESTINATION "${CMAKE_BINARY_DIR}/$<CONFIG>")
install(EXPORT foo DESTINATION lib/foo NAMESPACE foo-install::)
install(FILES foo-config.cmake.in RENAME foo-config.cmake DESTINATION lib/foo)
export(TARGETS foo NAMESPACE foo-build:: FILE Release/foo.cmake)

View File

@ -0,0 +1,54 @@
enable_language(C)
find_package(foo REQUIRED CONFIG NO_DEFAULT_PATH)
add_executable(main main.c)
target_link_libraries(main PRIVATE foo-install::foo)
get_property(enable_exports TARGET foo-install::foo PROPERTY ENABLE_EXPORTS)
if (CMAKE_TAPI AND NOT enable_exports)
message(SEND_ERROR "foo-install::foo: ENABLE_EXPORTS not set.")
endif()
get_property(implib TARGET foo-install::foo PROPERTY IMPORTED_IMPLIB_RELEASE)
if (CMAKE_TAPI AND NOT implib)
message(SEND_ERROR "foo-install::foo: IMPORTED_IMPLIB_RELEASE not set.")
endif()
if (CMAKE_TAPI AND NOT implib MATCHES "Release/libfoo.tbd$")
message(SEND_ERROR "foo-install::foo: ${implib}: wrong value for IMPORTED_IMPLIB_RELEASE.")
endif()
get_property(location TARGET foo-install::foo PROPERTY IMPORTED_LOCATION_RELEASE)
if (NOT location)
message(SEND_ERROR "foo-install::foo: IMPORTED_LOCATION_RELEASE not set.")
endif()
if (NOT location MATCHES "Release/libfoo.dylib$")
message(SEND_ERROR "foo-install::foo: ${location}: wrong value for IMPORTED_LOCATION_RELEASE.")
endif()
include(${foo_BUILD}/foo.cmake)
add_executable(main2 main.c)
target_link_libraries(main2 PRIVATE foo-build::foo)
get_property(enable_exports TARGET foo-build::foo PROPERTY ENABLE_EXPORTS)
if (CMAKE_TAPI AND NOT enable_exports)
message(SEND_ERROR "foo-build::foo: ENABLE_EXPORTS not set.")
endif()
get_property(implib TARGET foo-build::foo PROPERTY IMPORTED_IMPLIB_RELEASE)
if (CMAKE_TAPI AND NOT implib)
message(SEND_ERROR "foo-build::foo: IMPORTED_IMPLIB_RELEASE not set.")
endif()
if (CMAKE_TAPI AND NOT implib STREQUAL "${foo_BUILD}/libfoo.tbd")
message(SEND_ERROR "foo-build::foo: ${implib}: wrong value for IMPORTED_IMPLIB_RELEASE.")
endif()
get_property(location TARGET foo-build::foo PROPERTY IMPORTED_LOCATION_RELEASE)
if (NOT location)
message(SEND_ERROR "foo-build::foo: IMPORTED_LOCATION_RELEASE not set.")
endif()
if (NOT location STREQUAL "${foo_BUILD}/libfoo.dylib")
message(SEND_ERROR "foo-build::foo: ${location}: wrong value for IMPORTED_LOCATION_RELEASE.")
endif()

View File

@ -0,0 +1 @@
include ("${RunCMake_TEST_BINARY_DIR}/LibraryWithOutputs-Release-generated.cmake")

View File

@ -0,0 +1,52 @@
enable_language(C)
add_library(foo SHARED foo.c)
set_property(TARGET foo PROPERTY ENABLE_EXPORTS TRUE)
set_property(TARGET foo PROPERTY ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/TBD/$<CONFIG>")
set_property(TARGET foo PROPERTY ARCHIVE_OUTPUT_NAME "tbd")
add_executable(main main.c)
target_link_libraries(main PRIVATE foo)
set (GENERATE_CONTENT "if (\"${CMAKE_TAPI}\")
set (APPLE_TEXT_STUBS_SUPPORTED TRUE)
endif()\n\n")
string (APPEND GENERATE_CONTENT [[
macro (CHECK_FILE test_msg path)
if (NOT EXISTS "${path}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${path}\" not found\n")
endif()
endmacro()
check_file("DYLIB file" "$<TARGET_FILE:foo>")
check_file("executable file" "$<TARGET_FILE:main>")
if (APPLE_TEXT_STUBS_SUPPORTED)
check_file("TBD file" "$<TARGET_IMPORT_FILE:foo>")
]])
if (CMAKE_GENERATOR STREQUAL "Xcode")
# ARCHIVE outputs are ignored by this generator
string (APPEND GENERATE_CONTENT
"\n if (NOT \"$<TARGET_IMPORT_FILE_DIR:foo>\" STREQUAL \"${CMAKE_BINARY_DIR}/$<CONFIG>\")
string (APPEND RunCMake_TEST_FAILED \"Wrong directory for TBD file: \\\"$<TARGET_IMPORT_FILE_DIR:foo>\\\"\n\")
endif()
if (NOT \"$<TARGET_IMPORT_FILE_BASE_NAME:foo>\" STREQUAL \"foo\")
string (APPEND RunCMake_TEST_FAILED \"Wrong base name for TBD file: \\\"$<TARGET_IMPORT_FILE_BASE_NAME:foo>\\\"\n\")
endif()\n")
else()
string (APPEND GENERATE_CONTENT
"\n if (NOT \"$<TARGET_IMPORT_FILE_DIR:foo>\" STREQUAL \"${CMAKE_BINARY_DIR}/TBD/$<CONFIG>\")
string (APPEND RunCMake_TEST_FAILED \"Wrong directory for TBD file: \\\"$<TARGET_IMPORT_FILE_DIR:foo>\\\"\n\")
endif()
if (NOT \"$<TARGET_IMPORT_FILE_BASE_NAME:foo>\" STREQUAL \"tbd\")
string (APPEND RunCMake_TEST_FAILED \"Wrong base name for TBD file: \\\"$<TARGET_IMPORT_FILE_BASE_NAME:foo>\\\"\n\")
endif()\n")
endif()
string (APPEND GENERATE_CONTENT "endif()\n")
file (GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/LibraryWithOutputs-$<CONFIG>-generated.cmake"
CONTENT "${GENERATE_CONTENT}")

View File

@ -0,0 +1 @@
include ("${RunCMake_TEST_BINARY_DIR}/LibraryWithVersions-Release-generated.cmake")

View File

@ -0,0 +1,96 @@
enable_language(C)
add_library(foo SHARED foo.c)
set_property(TARGET foo PROPERTY ENABLE_EXPORTS TRUE)
set_property (TARGET foo PROPERTY VERSION 2.5.0)
set_property (TARGET foo PROPERTY SOVERSION 2.0.0)
add_executable(main main.c)
target_link_libraries(main PRIVATE foo)
install(TARGETS foo DESTINATION "${CMAKE_BINARY_DIR}/INSTALL" COMPONENT default)
install(TARGETS foo ARCHIVE DESTINATION "${CMAKE_BINARY_DIR}/INSTALL2/dev1" NAMELINK_SKIP COMPONENT default)
install(TARGETS foo ARCHIVE DESTINATION "${CMAKE_BINARY_DIR}/INSTALL2/dev2" NAMELINK_ONLY COMPONENT default)
install(TARGETS foo ARCHIVE DESTINATION "${CMAKE_BINARY_DIR}/INSTALL3"
COMPONENT lib3 NAMELINK_COMPONENT dev3)
install(TARGETS foo ARCHIVE DESTINATION "${CMAKE_BINARY_DIR}/INSTALL4"
COMPONENT lib4 NAMELINK_COMPONENT dev4)
set (GENERATE_CONTENT "if (\"${CMAKE_TAPI}\")
set (APPLE_TEXT_STUBS_SUPPORTED TRUE)
endif()\n\n")
string (APPEND GENERATE_CONTENT [[
cmake_policy (SET CMP0011 NEW)
cmake_policy (SET CMP0057 NEW)
macro (CHECK_FILE test_msg path)
if (NOT EXISTS "${path}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${path}\" not found\n")
endif()
endmacro()
macro (CHECK_SYMLINK test_msg path)
if (NOT IS_SYMLINK "${path}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${path}\" is not a symbolic link\n")
elseif (NOT EXISTS "${path}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${path}\" not a valid symlink\n")
endif()
endmacro()
macro (CHECK_NOFILE test_msg path)
if (EXISTS "${path}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${path}\" was found\n")
endif()
endmacro()
macro (CHECK_INSTALLED test_msg dir file)
file(GLOB installed_files LIST_DIRECTORIES FALSE RELATIVE "${dir}" "${dir}/*")
if (NOT "${file}" IN_LIST installed_files)
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${dir}/${file}\" not found\n")
endif()
endmacro()
check_file("DYLIB file" "$<TARGET_FILE:foo>")
check_symlink("Linkable DYLIB file" "$<TARGET_LINKER_LIBRARY_FILE:foo>")
check_symlink("SONAME DYLIB file" "$<TARGET_SONAME_FILE:foo>")
check_file("executable file" "$<TARGET_FILE:main>")
check_file("Installed DYLIB file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/$<TARGET_FILE_NAME:foo>")
check_symlink("Installed Linkable DYLIB file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/$<TARGET_LINKER_LIBRARY_FILE_NAME:foo>")
check_symlink("Installed SONAME DYLIB file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/$<TARGET_SONAME_FILE_NAME:foo>")
if (APPLE_TEXT_STUBS_SUPPORTED)
check_file("TBD file" "$<TARGET_IMPORT_FILE:foo>")
check_symlink("Linkable TBD file" "$<TARGET_LINKER_IMPORT_FILE:foo>")
check_symlink("SONAME TBD file" "$<TARGET_SONAME_IMPORT_FILE:foo>")
check_file("Installed TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/$<TARGET_IMPORT_FILE_NAME:foo>")
check_symlink("Installed Linkable TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/$<TARGET_LINKER_IMPORT_FILE_NAME:foo>")
check_symlink("Installed SONAME TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/$<TARGET_SONAME_IMPORT_FILE_NAME:foo>")
check_file("Installed TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/dev1/$<TARGET_IMPORT_FILE_NAME:foo>")
check_symlink("Installed SONAME TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/dev1/$<TARGET_SONAME_IMPORT_FILE_NAME:foo>")
check_nofile("Installed Linkable TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/dev1/$<TARGET_LINKER_IMPORT_FILE_NAME:foo>")
check_installed("Installed Linkable TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/dev2" "$<TARGET_LINKER_IMPORT_FILE_NAME:foo>")
check_nofile("Installed TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/dev2/$<TARGET_IMPORT_FILE_NAME:foo>")
check_nofile("Installed SONAME TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/dev2/$<TARGET_SONAME_IMPORT_FILE_NAME:foo>")
check_file("Installed TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL3/$<TARGET_IMPORT_FILE_NAME:foo>")
check_symlink("Installed SONAME TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL3/$<TARGET_SONAME_IMPORT_FILE_NAME:foo>")
check_nofile("Installed Linkable TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL3/$<TARGET_LINKER_IMPORT_FILE_NAME:foo>")
check_file("Installed TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL4/$<TARGET_IMPORT_FILE_NAME:foo>")
check_symlink("Installed SONAME TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL4/$<TARGET_SONAME_IMPORT_FILE_NAME:foo>")
check_symlink("Installed Linkable TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL4/$<TARGET_LINKER_IMPORT_FILE_NAME:foo>")
endif()
]])
file (GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/LibraryWithVersions-$<CONFIG>-generated.cmake"
CONTENT "${GENERATE_CONTENT}")

View File

@ -0,0 +1,58 @@
include(RunCMake)
function(build_project test)
if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
endif()
run_cmake(${test})
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Release)
if ("${ARGC}" GREATER "1")
# custom install step
cmake_language(CALL ${ARGV1})
else()
run_cmake_command(${test}-install ${CMAKE_COMMAND} --install . --config Release)
endif()
endfunction()
build_project(Simple)
build_project(Framework)
build_project(LibraryWithOutputs)
function(LibraryWithVersions-install)
run_cmake_command(LibraryWithVersions-install-component-lib3 ${CMAKE_COMMAND} --install . --config Release --component lib3)
run_cmake_command(LibraryWithVersions-install-component-lib4 ${CMAKE_COMMAND} --install . --config Release --component lib4)
run_cmake_command(LibraryWithVersions-install-components-dev4 ${CMAKE_COMMAND} --install . --config Release --component dev4)
run_cmake_command(LibraryWithVersions-install ${CMAKE_COMMAND} --install . --config Release --component default)
endfunction()
build_project(LibraryWithVersions LibraryWithVersions-install)
function(build_ExportImport_project test)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-export-build)
set(CMAKE_INSTALL_PREFIX ${RunCMake_TEST_BINARY_DIR}/root)
if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
endif()
run_cmake(${test}-export)
unset(RunCMake_TEST_OPTIONS)
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(${test}-export-build ${CMAKE_COMMAND} --build . --config Release)
run_cmake_command(${test}-export-install ${CMAKE_COMMAND} --install . --prefix ${CMAKE_INSTALL_PREFIX} --config Release)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-import-build)
set (foo_BUILD "${RunCMake_BINARY_DIR}/${test}-export-build")
if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
string (APPEND foo_BUILD "/Release")
endif()
run_cmake_with_options(${test}-import -Dfoo_DIR=${CMAKE_INSTALL_PREFIX}/lib/foo
-Dfoo_BUILD=${RunCMake_BINARY_DIR}/${test}-export-build/Release)
run_cmake_command(${test}-import-build ${CMAKE_COMMAND} --build . --config Release)
endfunction()
build_ExportImport_project(Library)
build_ExportImport_project(Framework)

View File

@ -0,0 +1 @@
include ("${RunCMake_TEST_BINARY_DIR}/Simple-Release-generated.cmake")

View File

@ -0,0 +1,41 @@
enable_language(C)
add_library(foo SHARED foo.c)
set_property(TARGET foo PROPERTY ENABLE_EXPORTS TRUE)
add_executable(main main.c)
target_link_libraries(main PRIVATE foo)
install(TARGETS foo DESTINATION "${CMAKE_BINARY_DIR}/INSTALL")
install(TARGETS foo LIBRARY DESTINATION "${CMAKE_BINARY_DIR}/INSTALL2/lib"
ARCHIVE DESTINATION "${CMAKE_BINARY_DIR}/INSTALL2/dev")
set (GENERATE_CONTENT "if (\"${CMAKE_TAPI}\")
set (APPLE_TEXT_STUBS_SUPPORTED TRUE)
endif()\n\n")
string (APPEND GENERATE_CONTENT [[
macro (CHECK_FILE test_msg path)
if (NOT EXISTS "${path}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: \"${path}\" not found\n")
endif()
endmacro()
check_file("DYLIB file" "$<TARGET_FILE:foo>")
check_file("executable file" "$<TARGET_FILE:main>")
check_file("Installed DYLIB file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/lib/$<TARGET_FILE_NAME:foo>")
if (APPLE_TEXT_STUBS_SUPPORTED)
check_file("TBD file" "$<TARGET_IMPORT_FILE:foo>")
check_file("Installed TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL/$<TARGET_IMPORT_FILE_NAME:foo>")
check_file("Installed TBD file" "${RunCMake_TEST_BINARY_DIR}/INSTALL2/dev/$<TARGET_IMPORT_FILE_NAME:foo>")
endif()
]])
file (GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Simple-$<CONFIG>-generated.cmake"
CONTENT "${GENERATE_CONTENT}")

View File

@ -0,0 +1 @@
include(${CMAKE_CURRENT_LIST_DIR}/foo.cmake)

View File

@ -0,0 +1,5 @@
int foo()
{
return 0;
}

View File

@ -0,0 +1,7 @@
extern int foo(void);
int main()
{
return foo();
}

View File

@ -357,6 +357,7 @@ add_RunCMake_test(GenEx-DEVICE_LINK)
add_RunCMake_test(GenEx-LINK_LIBRARY)
add_RunCMake_test(GenEx-LINK_GROUP)
add_RunCMake_test(GenEx-TARGET_FILE -DLINKER_SUPPORTS_PDB=${LINKER_SUPPORTS_PDB})
add_RunCMake_test(GenEx-TARGET_IMPORT_FILE)
add_RunCMake_test(GenEx-GENEX_EVAL)
add_RunCMake_test(GenEx-TARGET_PROPERTY)
add_RunCMake_test(GenEx-TARGET_RUNTIME_DLLS)
@ -515,6 +516,7 @@ add_RunCMake_test(BundleUtilities)
if(APPLE)
add_RunCMake_test(INSTALL_NAME_DIR)
add_RunCMake_test(MacOSVersions)
add_RunCMake_test(AppleTextStubs)
endif()
function(add_RunCMake_test_try_compile)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.5)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,21 @@
include(RunCMake)
cmake_policy(SET CMP0057 NEW)
function(run_cmake_with_config test)
if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
endif()
run_cmake(${test})
endfunction()
run_cmake(TARGET_LINKER_IMPORT_FILE-non-valid-target)
run_cmake(TARGET_LINKER_LIBRARY_FILE-non-valid-target)
run_cmake_with_config(TARGET_IMPORT_FILE)
run_cmake_with_config(TARGET_IMPORT_FILE_SUFFIX)
set (Windows_platforms Windows CYGWIN MSYS)
if (NOT CMAKE_HOST_SYSTEM_NAME IN_LIST Windows_platforms)
run_cmake(TARGET_SONAME_IMPORT_FILE-non-valid-target)
run_cmake_with_config(TARGET_SONAME_IMPORT_FILE)
endif()

View File

@ -0,0 +1 @@
include ("${RunCMake_TEST_BINARY_DIR}/TARGET_IMPORT_FILE-Release-generated.cmake")

View File

@ -0,0 +1,47 @@
enable_language(C)
set (platforms_with_import Windows CYGWIN MSYS)
set (GENERATE_CONTENT [[
macro (CHECK_VALUE test_msg value expected)
if (NOT "${value}" STREQUAL "${expected}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: actual result:\n [${value}]\nbut expected:\n [${expected}]\n")
endif()
endmacro()
]])
add_library (shared1 SHARED empty.c)
add_library (static1 STATIC empty.c)
add_executable (exec1 empty.c)
string (APPEND GENERATE_CONTENT
"\ncheck_value (\"TARGET_IMPORT_FILE shared library\" \"$<TARGET_IMPORT_FILE:shared1>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${platforms_with_import}>,$<TARGET_LINKER_IMPORT_FILE:shared1>,>\")
check_value (\"TARGET_LINKER_FILE shared library\" \"$<TARGET_LINKER_FILE:shared1>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${platforms_with_import}>,$<TARGET_LINKER_IMPORT_FILE:shared1>,$<TARGET_LINKER_LIBRARY_FILE:shared1>>\")
check_value (\"TARGET_IMPORT_FILE static library\" \"$<TARGET_IMPORT_FILE:static1>\" \"\")
check_value (\"TARGET_IMPORT_FILE executable\" \"$<TARGET_IMPORT_FILE:exec1>\" \"\")\n")
set(lib_with_import ${platforms_with_import})
set(exec_with_import ${platforms_with_import})
if (APPLE AND CMAKE_TAPI)
list(APPEND lib_with_import Darwin)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "AIX")
list(APPEND exec_with_import "AIX")
endif()
set(CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS TRUE)
set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE)
add_library (shared2 SHARED empty.c)
add_executable (exec2 empty.c)
string (APPEND GENERATE_CONTENT
"\ncheck_value (\"TARGET_IMPORT_FILE shared library\" \"$<TARGET_IMPORT_FILE:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${lib_with_import}>,$<TARGET_LINKER_IMPORT_FILE:shared2>,>\")
check_value (\"TARGET_LINKER_FILE shared library\" \"$<TARGET_LINKER_FILE:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${lib_with_import}>,$<TARGET_LINKER_IMPORT_FILE:shared2>,$<TARGET_LINKER_LIBRARY_FILE:shared2>>\")
check_value (\"TARGET_IMPORT_FILE executable\" \"$<TARGET_IMPORT_FILE:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${exec_with_import}>,$<TARGET_LINKER_IMPORT_FILE:exec2>,>\")\n")
file (GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/TARGET_IMPORT_FILE-$<CONFIG>-generated.cmake"
CONTENT "${GENERATE_CONTENT}")

View File

@ -0,0 +1 @@
include ("${RunCMake_TEST_BINARY_DIR}/TARGET_IMPORT_FILE_SUFFIX-Release-generated.cmake")

View File

@ -0,0 +1,44 @@
enable_language (C)
set (platforms_with_import Windows CYGWIN MSYS)
set (GENERATE_CONTENT [[
macro (CHECK_VALUE test_msg value expected)
if (NOT "${value}" STREQUAL "${expected}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: actual result:\n [${value}]\nbut expected:\n [${expected}]\n")
endif()
endmacro()
]])
add_library (shared1 SHARED empty.c)
add_library (static1 STATIC empty.c)
add_executable (exec1 empty.c)
string (APPEND GENERATE_CONTENT
"\ncheck_value (\"TARGET_IMPORT_FILE_SUFFIX executable default\" \"$<TARGET_IMPORT_FILE_SUFFIX:exec1>\" \"\")
check_value (\"TARGET_IMPORT_FILE_SUFFIX shared default\" \"$<TARGET_IMPORT_FILE_SUFFIX:shared1>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${platforms_with_import}>,$<TARGET_LINKER_IMPORT_FILE_SUFFIX:shared1>,>\")
check_value (\"TARGET_FILE_SUFFIX static default\" \"$<TARGET_IMPORT_FILE_SUFFIX:static1>\" \"\")
check_value (\"TARGET_IMPORT_FILE_SUFFIX executable default\" \"$<TARGET_IMPORT_FILE_SUFFIX:exec1>\" \"\")\n")
if (APPLE AND CMAKE_TAPI)
list(APPEND platforms_with_import Darwin)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "AIX")
list(APPEND platforms_with_import AIX)
endif()
set(CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS TRUE)
set(CMAKE_EXECUTABLE_ENABLE_EXPORTS TRUE)
add_library (shared2 SHARED empty.c)
add_executable (exec2 empty.c)
string (APPEND GENERATE_CONTENT
"\ncheck_value (\"TARGET_IMPORT_FILE_SUFFIX executable default\" \"$<TARGET_IMPORT_FILE_SUFFIX:exec2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${platforms_with_import}>,$<TARGET_LINKER_IMPORT_FILE_SUFFIX:exec2>,>\")
check_value (\"TARGET_IMPORT_FILE_SUFFIX shared default\" \"$<TARGET_IMPORT_FILE_SUFFIX:shared2>\" \"$<IF:$<IN_LIST:$<PLATFORM_ID>,${platforms_with_import}>,$<TARGET_LINKER_IMPORT_FILE_SUFFIX:shared2>,>\")\n")
file (GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/TARGET_IMPORT_FILE_SUFFIX-$<CONFIG>-generated.cmake"
CONTENT "${GENERATE_CONTENT}")

View File

@ -0,0 +1,9 @@
CMake Error at TARGET_LINKER_IMPORT_FILE-non-valid-target.cmake:[0-9]+ \(file\):
Error evaluating generator expression:
\$<TARGET_LINKER_IMPORT_FILE:exe1>
TARGET_LINKER_IMPORT_FILE is allowed only for libraries and executables
with ENABLE_EXPORTS.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@ -0,0 +1,9 @@
enable_language(C)
add_executable(exe1 empty.c)
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
CONTENT "[$<TARGET_LINKER_IMPORT_FILE:exe1>]"
)

View File

@ -0,0 +1,9 @@
CMake Error at TARGET_LINKER_LIBRARY_FILE-non-valid-target.cmake:[0-9]+ \(file\):
Error evaluating generator expression:
\$<TARGET_LINKER_LIBRARY_FILE:exe1>
TARGET_LINKER_LIBRARY_FILE is allowed only for libraries with
ENABLE_EXPORTS.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@ -0,0 +1,9 @@
enable_language(C)
add_executable(exe1 empty.c)
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
CONTENT "[$<TARGET_LINKER_LIBRARY_FILE:exe1>]"
)

View File

@ -0,0 +1 @@
include ("${RunCMake_TEST_BINARY_DIR}/TARGET_SONAME_IMPORT_FILE-Release-generated.cmake")

View File

@ -0,0 +1,8 @@
CMake Error at TARGET_SONAME_IMPORT_FILE-non-valid-target.cmake:[0-9]+ \(file\):
Error evaluating generator expression:
\$<TARGET_SONAME_IMPORT_FILE:static1>
TARGET_SONAME_IMPORT_FILE is allowed only for SHARED libraries.
Call Stack \(most recent call first\):
CMakeLists.txt:[0-9]+ \(include\)

View File

@ -0,0 +1,8 @@
enable_language(C)
add_library (static1 STATIC empty.c)
set_property (TARGET static1 PROPERTY VERSION 2.5.0)
set_property (TARGET static1 PROPERTY SOVERSION 2.0.0)
file (GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/test.txt"
CONTENT "[$<TARGET_SONAME_IMPORT_FILE:static1>]")

View File

@ -0,0 +1,32 @@
enable_language(C)
set (GENERATE_CONTENT [[
macro (CHECK_VALUE test_msg value expected)
if (NOT "${value}" STREQUAL "${expected}")
string (APPEND RunCMake_TEST_FAILED "${test_msg}: actual result:\n [${value}]\nbut expected:\n [${expected}]\n")
endif()
endmacro()
]])
add_library (shared1 SHARED empty.c)
set_property (TARGET shared1 PROPERTY VERSION 2.5.0)
set_property (TARGET shared1 PROPERTY SOVERSION 2.0.0)
string (APPEND GENERATE_CONTENT
"\ncheck_value (\"TARGET_SONAME_IMPORT_FILE shared library\" \"$<TARGET_SONAME_IMPORT_FILE:shared1>\" \"\")\n")
add_library (shared2 SHARED empty.c)
set_property(TARGET shared2 PROPERTY ENABLE_EXPORTS ON)
set_property (TARGET shared2 PROPERTY VERSION 2.5.0)
set_property (TARGET shared2 PROPERTY SOVERSION 2.0.0)
string (APPEND GENERATE_CONTENT
"\ncheck_value (\"TARGET_SONAME_IMPORT_FILE shared library\" \"$<TARGET_SONAME_IMPORT_FILE:shared2>\" \"$<$<BOOL:${CMAKE_TAPI}>:$<PATH:REPLACE_EXTENSION,LAST_ONLY,$<TARGET_SONAME_FILE:shared2>,.tbd>>\")\n")
file (GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/TARGET_SONAME_IMPORT_FILE-$<CONFIG>-generated.cmake"
CONTENT "${GENERATE_CONTENT}")

View File

@ -1,5 +1,6 @@
^CMake Error at TARGETS-NAMELINK_COMPONENT-bad-all\.cmake:5 \(install\):
install TARGETS given NAMELINK_COMPONENT option not in LIBRARY group\. The
NAMELINK_COMPONENT option may be specified only following LIBRARY\.
install TARGETS given NAMELINK_COMPONENT option not in LIBRARY or ARCHIVE
group\. The NAMELINK_COMPONENT option may be specified only following
LIBRARY or ARCHIVE\.
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)$

View File

@ -1,5 +1,6 @@
^CMake Error at TARGETS-NAMELINK_COMPONENT-bad-exc\.cmake:5 \(install\):
install TARGETS given NAMELINK_COMPONENT option not in LIBRARY group\. The
NAMELINK_COMPONENT option may be specified only following LIBRARY\.
install TARGETS given NAMELINK_COMPONENT option not in LIBRARY or ARCHIVE
group\. The NAMELINK_COMPONENT option may be specified only following
LIBRARY or ARCHIVE\.
Call Stack \(most recent call first\):
CMakeLists\.txt:[0-9]+ \(include\)$