summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--CompileFlags.cmake2
-rw-r--r--Help/command/export.rst15
-rw-r--r--Help/command/file.rst3
-rw-r--r--Help/command/install.rst14
-rw-r--r--Help/command/separate_arguments.rst12
-rw-r--r--Help/command/string.rst2
-rw-r--r--Help/manual/cmake-variables.7.rst4
-rw-r--r--Help/release/dev/add_androidmk_generator.rst10
-rw-r--r--Help/release/dev/cmake-gui-open-project.rst5
-rw-r--r--Help/release/dev/file-curl-userpw.rst5
-rw-r--r--Help/release/dev/timestamp-names.rst6
-rw-r--r--Help/variable/CMAKE_COMPILER_IS_GNUCC.rst5
-rw-r--r--Help/variable/CMAKE_COMPILER_IS_GNUCXX.rst5
-rw-r--r--Help/variable/CMAKE_COMPILER_IS_GNUG77.rst5
-rw-r--r--Help/variable/CMAKE_COMPILER_IS_GNULANG.rst15
-rw-r--r--Modules/FindMatlab.cmake51
-rw-r--r--Modules/FindPythonInterp.cmake2
-rw-r--r--Modules/FindPythonLibs.cmake2
-rw-r--r--Modules/GenerateExportHeader.cmake2
-rw-r--r--Modules/MatlabTestsRedirect.cmake41
-rw-r--r--Source/CMakeLists.txt4
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestSVN.cxx17
-rw-r--r--Source/CTest/cmCTestSVN.h2
-rw-r--r--Source/CursesDialog/cmCursesStandardIncludes.h4
-rw-r--r--Source/CursesDialog/form/form.h4
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx37
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h2
-rw-r--r--Source/QtDialog/CMakeSetupDialog.ui7
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx193
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.h68
-rw-r--r--Source/cmExportCommand.cxx18
-rw-r--r--Source/cmExportCommand.h1
-rw-r--r--Source/cmExportFileGenerator.cxx45
-rw-r--r--Source/cmExportFileGenerator.h39
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.cxx146
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.h72
-rw-r--r--Source/cmExportInstallFileGenerator.cxx153
-rw-r--r--Source/cmExportInstallFileGenerator.h12
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx5
-rw-r--r--Source/cmFileCommand.cxx36
-rw-r--r--Source/cmGeneratorTarget.cxx6
-rw-r--r--Source/cmGlobalGenerator.cxx88
-rw-r--r--Source/cmInstallCommand.cxx98
-rw-r--r--Source/cmInstallCommand.h1
-rw-r--r--Source/cmInstallExportAndroidMKGenerator.cxx149
-rw-r--r--Source/cmInstallExportAndroidMKGenerator.h46
-rw-r--r--Source/cmInstallExportGenerator.cxx13
-rw-r--r--Source/cmInstallExportGenerator.h3
-rw-r--r--Source/cmInstallTargetsCommand.cxx17
-rw-r--r--Source/cmLocalGenerator.cxx21
-rw-r--r--Source/cmMakefile.cxx21
-rw-r--r--Source/cmSystemTools.cxx77
-rw-r--r--Source/cmSystemTools.h10
-rw-r--r--Source/cmTarget.cxx35
-rw-r--r--Source/cmTarget.h26
-rw-r--r--Source/cmTimestamp.cxx2
-rw-r--r--Source/cmake.cxx57
-rw-r--r--Source/cmake.h10
-rw-r--r--Source/cmcmd.cxx2
-rw-r--r--Tests/CMakeLib/testSystemTools.cxx72
-rw-r--r--Tests/CMakeTests/String-TIMESTAMP-MonthWeekNames.cmake11
-rw-r--r--Tests/CMakeTests/StringTest.cmake.in3
-rw-r--r--Tests/RunCMake/AndroidMK/AndroidMK-check.cmake30
-rw-r--r--Tests/RunCMake/AndroidMK/AndroidMK.cmake11
-rw-r--r--Tests/RunCMake/AndroidMK/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/AndroidMK/RunCMakeTest.cmake2
-rw-r--r--Tests/RunCMake/AndroidMK/expectedBuildAndroidMK.txt23
-rw-r--r--Tests/RunCMake/AndroidMK/expectedInstallAndroidMK.txt25
-rw-r--r--Tests/RunCMake/AndroidMK/foo.cxx3
-rw-r--r--Tests/RunCMake/CMakeLists.txt2
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-pass-not-set-result.txt1
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-pass-not-set-stderr.txt4
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-pass-not-set.cmake1
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-unused-argument-result.txt0
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-unused-argument-stderr.txt5
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake5
-rw-r--r--Tests/RunCMake/file/DOWNLOAD-unused-argument.txt0
-rw-r--r--Tests/RunCMake/file/RunCMakeTest.cmake4
-rw-r--r--Tests/RunCMake/file/UPLOAD-pass-not-set-result.txt1
-rw-r--r--Tests/RunCMake/file/UPLOAD-pass-not-set-stderr.txt4
-rw-r--r--Tests/RunCMake/file/UPLOAD-pass-not-set.cmake1
-rw-r--r--Tests/RunCMake/file/UPLOAD-unused-argument-result.txt0
-rw-r--r--Tests/RunCMake/file/UPLOAD-unused-argument-stderr.txt5
-rw-r--r--Tests/RunCMake/file/UPLOAD-unused-argument.cmake5
-rw-r--r--Tests/RunCMake/file/UPLOAD-unused-argument.txt0
87 files changed, 1680 insertions, 301 deletions
diff --git a/.gitignore b/.gitignore
index 0d09cdc..5d1732d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,7 @@
# Exclude MacOS Finder files.
.DS_Store
+
+*.user*
+
+*.pyc
+Testing
diff --git a/CompileFlags.cmake b/CompileFlags.cmake
index 3c053fa..535f68b 100644
--- a/CompileFlags.cmake
+++ b/CompileFlags.cmake
@@ -64,7 +64,7 @@ endif()
# Workaround for short jump tables on PA-RISC
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^parisc")
- if(CMAKE_COMPILER_IS_GNUC)
+ if(CMAKE_COMPILER_IS_GNUCC)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-calls")
endif()
if(CMAKE_COMPILER_IS_GNUCXX)
diff --git a/Help/command/export.rst b/Help/command/export.rst
index 4419dc1..53675a7 100644
--- a/Help/command/export.rst
+++ b/Help/command/export.rst
@@ -55,3 +55,18 @@ build tree. In some cases, for example for packaging and for system
wide installations, it is not desirable to write the user package
registry. If the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable
is enabled, the ``export(PACKAGE)`` command will do nothing.
+
+::
+
+ export(TARGETS [target1 [target2 [...]]] [ANDROID_MK <filename>])
+
+This signature exports cmake built targets to the android ndk build system
+by creating an Android.mk file that references the prebuilt targets. The
+Android NDK supports the use of prebuilt libraries, both static and shared.
+This allows cmake to build the libraries of a project and make them available
+to an ndk build system complete with transitive dependencies, include flags
+and defines required to use the libraries. The signature takes a list of
+targets and puts them in the Android.mk file specified by the ``<filename>``
+given. This signature can only be used if policy CMP0022 is NEW for all
+targets given. A error will be issued if that policy is set to OLD for one
+of the targets.
diff --git a/Help/command/file.rst b/Help/command/file.rst
index 256d16d..f8727f0 100644
--- a/Help/command/file.rst
+++ b/Help/command/file.rst
@@ -222,6 +222,9 @@ Options to both ``DOWNLOAD`` and ``UPLOAD`` are:
``TIMEOUT <seconds>``
Terminate the operation after a given total time has elapsed.
+``USERPWD <username>:<password>``
+ Set username and password for operation.
+
Additional options to ``DOWNLOAD`` are:
``EXPECTED_HASH ALGO=<value>``
diff --git a/Help/command/install.rst b/Help/command/install.rst
index aaf12cc..d57dd75 100644
--- a/Help/command/install.rst
+++ b/Help/command/install.rst
@@ -314,7 +314,8 @@ Installing Exports
::
install(EXPORT <export-name> DESTINATION <dir>
- [NAMESPACE <namespace>] [FILE <name>.cmake]
+ [NAMESPACE <namespace>] [[FILE <name>.cmake]|
+ [EXPORT_ANDROID_MK <name>.mk]]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[EXPORT_LINK_INTERFACE_LIBRARIES]
@@ -342,6 +343,13 @@ specified that does not match that given to the targets associated with
included in the export but a target to which it links is not included
the behavior is unspecified.
+In additon to cmake language files, the ``EXPORT_ANDROID_MK`` option maybe
+used to specifiy an export to the android ndk build system. The Android
+NDK supports the use of prebuilt libraries, both static and shared. This
+allows cmake to build the libraries of a project and make them available
+to an ndk build system complete with transitive dependencies, include flags
+and defines required to use the libraries.
+
The ``EXPORT`` form is useful to help outside projects use targets built
and installed by the current project. For example, the code
@@ -349,9 +357,11 @@ and installed by the current project. For example, the code
install(TARGETS myexe EXPORT myproj DESTINATION bin)
install(EXPORT myproj NAMESPACE mp_ DESTINATION lib/myproj)
+ install(EXPORT_ANDROID_MK myexp DESTINATION share/ndk-modules)
will install the executable myexe to ``<prefix>/bin`` and code to import
-it in the file ``<prefix>/lib/myproj/myproj.cmake``. An outside project
+it in the file ``<prefix>/lib/myproj/myproj.cmake`` and
+``<prefix>/lib/share/ndk-modules/Android.mk``. An outside project
may load this file with the include command and reference the ``myexe``
executable from the installation tree using the imported target name
``mp_myexe`` as if the target were built in its own tree.
diff --git a/Help/command/separate_arguments.rst b/Help/command/separate_arguments.rst
index 0e3e5a5..1fd3cd1 100644
--- a/Help/command/separate_arguments.rst
+++ b/Help/command/separate_arguments.rst
@@ -13,19 +13,21 @@ entire command line must be given in one "<args>" argument.
The ``UNIX_COMMAND`` mode separates arguments by unquoted whitespace. It
recognizes both single-quote and double-quote pairs. A backslash
-escapes the next literal character (\" is "); there are no special
-escapes (\n is just n).
+escapes the next literal character (``\"`` is ``"``); there are no special
+escapes (``\n`` is just ``n``).
The ``WINDOWS_COMMAND`` mode parses a windows command-line using the same
syntax the runtime library uses to construct argv at startup. It
separates arguments by whitespace that is not double-quoted.
Backslashes are literal unless they precede double-quotes. See the
-MSDN article "Parsing C Command-Line Arguments" for details.
+MSDN article `Parsing C Command-Line Arguments`_ for details.
+
+.. _`Parsing C Command-Line Arguments`: https://msdn.microsoft.com/library/a1y7w461.aspx
::
- separate_arguments(VARIABLE)
+ separate_arguments(<var>)
-Convert the value of ``VARIABLE`` to a semi-colon separated list. All
+Convert the value of ``<var>`` to a semi-colon separated list. All
spaces are replaced with ';'. This helps with generating command
lines.
diff --git a/Help/command/string.rst b/Help/command/string.rst
index 19a095a..8028333 100644
--- a/Help/command/string.rst
+++ b/Help/command/string.rst
@@ -278,12 +278,14 @@ specifiers:
%I The hour on a 12-hour clock (01-12).
%j The day of the current year (001-366).
%m The month of the current year (01-12).
+ %b Abbreviated month name (e.g. Oct).
%M The minute of the current hour (00-59).
%s Seconds since midnight (UTC) 1-Jan-1970 (UNIX time).
%S The second of the current minute.
60 represents a leap second. (00-60)
%U The week number of the current year (00-53).
%w The day of the current week. 0 is Sunday. (0-6)
+ %a Abbreviated weekday name (e.g. Fri).
%y The last two digits of the current year (00-99)
%Y The current year.
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index b14f667..74c9265 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -332,7 +332,9 @@ Variables for Languages
.. toctree::
:maxdepth: 1
- /variable/CMAKE_COMPILER_IS_GNULANG
+ /variable/CMAKE_COMPILER_IS_GNUCC
+ /variable/CMAKE_COMPILER_IS_GNUCXX
+ /variable/CMAKE_COMPILER_IS_GNUG77
/variable/CMAKE_C_COMPILE_FEATURES
/variable/CMAKE_C_EXTENSIONS
/variable/CMAKE_C_STANDARD
diff --git a/Help/release/dev/add_androidmk_generator.rst b/Help/release/dev/add_androidmk_generator.rst
new file mode 100644
index 0000000..dd7867c
--- /dev/null
+++ b/Help/release/dev/add_androidmk_generator.rst
@@ -0,0 +1,10 @@
+add_androidmk_generator
+-----------------------
+
+* The :command:`install` command gained an ``EXPORT_ANDROID_MK``
+ subcommand to install ``Android.mk`` files referencing installed
+ libraries as prebuilts for the Android NDK build system.
+
+* The :command:`export` command gained an ``ANDROID_MK`` option
+ to generate ``Android.mk`` files referencing CMake-built
+ libraries as prebuilts for the Android NDK build system.
diff --git a/Help/release/dev/cmake-gui-open-project.rst b/Help/release/dev/cmake-gui-open-project.rst
new file mode 100644
index 0000000..32f0f0f
--- /dev/null
+++ b/Help/release/dev/cmake-gui-open-project.rst
@@ -0,0 +1,5 @@
+cmake-gui-open-project
+----------------------
+
+* :manual:`cmake-gui(1)` gained a button to open the generated project file
+ for :ref:`Visual Studio Generators` and the :generator:`Xcode` generator.
diff --git a/Help/release/dev/file-curl-userpw.rst b/Help/release/dev/file-curl-userpw.rst
new file mode 100644
index 0000000..4ae1fee
--- /dev/null
+++ b/Help/release/dev/file-curl-userpw.rst
@@ -0,0 +1,5 @@
+file-curl-userpw
+----------------
+
+* The :command:`file(DOWNLOAD)` and :command:`file(UPLOAD)` commands
+ gained a ``USERPWD <username>:<password>`` option.
diff --git a/Help/release/dev/timestamp-names.rst b/Help/release/dev/timestamp-names.rst
new file mode 100644
index 0000000..ea54b5c
--- /dev/null
+++ b/Help/release/dev/timestamp-names.rst
@@ -0,0 +1,6 @@
+timestamp-names
+---------------
+
+* The :command:`string(TIMESTAMP)` and :command:`file(TIMESTAMP)`
+ commands gained support for the ``%a`` and ``%b`` placeholders.
+ These are the abbreviated weekday and month names.
diff --git a/Help/variable/CMAKE_COMPILER_IS_GNUCC.rst b/Help/variable/CMAKE_COMPILER_IS_GNUCC.rst
new file mode 100644
index 0000000..a40667e
--- /dev/null
+++ b/Help/variable/CMAKE_COMPILER_IS_GNUCC.rst
@@ -0,0 +1,5 @@
+CMAKE_COMPILER_IS_GNUCC
+-----------------------
+
+True if the ``C`` compiler is GNU.
+Use :variable:`CMAKE_C_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` instead.
diff --git a/Help/variable/CMAKE_COMPILER_IS_GNUCXX.rst b/Help/variable/CMAKE_COMPILER_IS_GNUCXX.rst
new file mode 100644
index 0000000..f1f5cf7
--- /dev/null
+++ b/Help/variable/CMAKE_COMPILER_IS_GNUCXX.rst
@@ -0,0 +1,5 @@
+CMAKE_COMPILER_IS_GNUCXX
+------------------------
+
+True if the C++ (``CXX``) compiler is GNU.
+Use :variable:`CMAKE_CXX_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` instead.
diff --git a/Help/variable/CMAKE_COMPILER_IS_GNUG77.rst b/Help/variable/CMAKE_COMPILER_IS_GNUG77.rst
new file mode 100644
index 0000000..3d6dab4
--- /dev/null
+++ b/Help/variable/CMAKE_COMPILER_IS_GNUG77.rst
@@ -0,0 +1,5 @@
+CMAKE_COMPILER_IS_GNUG77
+------------------------
+
+True if the ``Fortran`` compiler is GNU.
+Use :variable:`CMAKE_Fortran_COMPILER_ID <CMAKE_<LANG>_COMPILER_ID>` instead.
diff --git a/Help/variable/CMAKE_COMPILER_IS_GNULANG.rst b/Help/variable/CMAKE_COMPILER_IS_GNULANG.rst
deleted file mode 100644
index 4b652c0..0000000
--- a/Help/variable/CMAKE_COMPILER_IS_GNULANG.rst
+++ /dev/null
@@ -1,15 +0,0 @@
-CMAKE_COMPILER_IS_GNU<LANG>
----------------------------
-
-True if the compiler is GNU.
-
-If the selected ``<LANG>`` compiler is the GNU compiler then this is ``TRUE``,
-if not it is ``FALSE``. Unlike the other per-language variables, this
-uses the GNU syntax for identifying languages instead of the CMake
-syntax. Recognized values of the ``<LANG>`` suffix are:
-
-::
-
- CC = C compiler
- CXX = C++ compiler
- G77 = Fortran compiler
diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake
index b501599..c813f8f 100644
--- a/Modules/FindMatlab.cmake
+++ b/Modules/FindMatlab.cmake
@@ -635,7 +635,7 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve
set(devnull INPUT_FILE NUL)
endif()
- # timeout set to 30 seconds, in case it does not start
+ # timeout set to 120 seconds, in case it does not start
# note as said before OUTPUT_VARIABLE cannot be used in a platform
# independent manner however, not setting it would flush the output of Matlab
# in the current console (unix variant)
@@ -644,11 +644,18 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve
OUTPUT_VARIABLE _matlab_version_from_cmd_dummy
RESULT_VARIABLE _matlab_result_version_call
ERROR_VARIABLE _matlab_result_version_call_error
- TIMEOUT 30
+ TIMEOUT 120
WORKING_DIRECTORY "${_matlab_temporary_folder}"
${devnull}
)
+ if("${_matlab_result_version_call}" MATCHES "timeout")
+ if(MATLAB_FIND_DEBUG)
+ message(WARNING "[MATLAB] Unable to determine the version of Matlab."
+ " Matlab call timed out after 120 seconds.")
+ endif()
+ return()
+ endif()
if(${_matlab_result_version_call})
if(MATLAB_FIND_DEBUG)
@@ -698,7 +705,6 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve
endfunction()
-
#.rst:
# .. command:: matlab_add_unit_test
#
@@ -720,6 +726,7 @@ endfunction()
# matlab_add_unit_test(
# NAME <name>
# UNITTEST_FILE matlab_file_containing_unittest.m
+# [CUSTOM_MATLAB_COMMAND matlab_command_to_run_as_test]
# [UNITTEST_PRECOMMAND matlab_command_to_run]
# [TIMEOUT timeout]
# [ADDITIONAL_PATH path1 [path2 ...]]
@@ -735,6 +742,11 @@ endfunction()
# ``UNITTEST_FILE``
# the matlab unittest file. Its path will be automatically
# added to the Matlab path.
+# ``CUSTOM_MATLAB_COMMAND``
+# Matlab script command to run as the test.
+# IIf this is not set, then the following is run:
+# "runtests('matlab_file_name'), exit(max([ans(1,:).Failed]))
+# matlab_file_name comes from UNITTEST_FILE without the .m.
# ``UNITTEST_PRECOMMAND``
# Matlab script command to be ran before the file
# containing the test (eg. GPU device initialisation based on CMake
@@ -748,12 +760,18 @@ endfunction()
# ``MATLAB_ADDITIONAL_STARTUP_OPTIONS``
# a list of additional option in order
# to run Matlab from the command line.
+# -nosplash -nodesktop -nodisplay are always added.
# ``TEST_ARGS``
# Additional options provided to the add_test command. These
# options are added to the default options (eg. "CONFIGURATIONS Release")
# ``NO_UNITTEST_FRAMEWORK``
# when set, indicates that the test should not
# use the unittest framework of Matlab (available for versions >= R2013a).
+# ``WORKING_DIRECTORY``
+# This will be the working directory for the test. If specified it will
+# also be the output directory used for the log file of the test run.
+# If not specifed the temporary directory ${CMAKE_BINARY_DIR}/Matlab will
+# be used as the working directory and the log location.
#
function(matlab_add_unit_test)
@@ -762,11 +780,12 @@ function(matlab_add_unit_test)
endif()
set(options NO_UNITTEST_FRAMEWORK)
- set(oneValueArgs NAME UNITTEST_PRECOMMAND UNITTEST_FILE TIMEOUT)
+ set(oneValueArgs NAME UNITTEST_FILE TIMEOUT WORKING_DIRECTORY
+ UNITTEST_PRECOMMAND CUSTOM_TEST_COMMAND)
set(multiValueArgs ADDITIONAL_PATH MATLAB_ADDITIONAL_STARTUP_OPTIONS TEST_ARGS)
set(prefix _matlab_unittest_prefix)
- cmake_parse_arguments(${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
+ cmake_parse_arguments(PARSE_ARGV 0 ${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" )
if(NOT ${prefix}_NAME)
message(FATAL_ERROR "[MATLAB] The Matlab test name cannot be empty")
@@ -774,15 +793,17 @@ function(matlab_add_unit_test)
add_test(NAME ${${prefix}_NAME}
COMMAND ${CMAKE_COMMAND}
- -Dtest_name=${${prefix}_NAME}
- -Dadditional_paths=${${prefix}_ADDITIONAL_PATH}
- -Dtest_timeout=${${prefix}_TIMEOUT}
- -Doutput_directory=${_matlab_temporary_folder}
- -DMatlab_PROGRAM=${Matlab_MAIN_PROGRAM}
- -Dno_unittest_framework=${${prefix}_NO_UNITTEST_FRAMEWORK}
- -DMatlab_ADDITIONNAL_STARTUP_OPTIONS=${${prefix}_MATLAB_ADDITIONAL_STARTUP_OPTIONS}
- -Dunittest_file_to_run=${${prefix}_UNITTEST_FILE}
- -Dcmd_to_run_before_test=${${prefix}_UNITTEST_PRECOMMAND}
+ "-Dtest_name=${${prefix}_NAME}"
+ "-Dadditional_paths=${${prefix}_ADDITIONAL_PATH}"
+ "-Dtest_timeout=${${prefix}_TIMEOUT}"
+ "-Doutput_directory=${_matlab_temporary_folder}"
+ "-Dworking_directory=${${prefix}_WORKING_DIRECTORY}"
+ "-DMatlab_PROGRAM=${Matlab_MAIN_PROGRAM}"
+ "-Dno_unittest_framework=${${prefix}_NO_UNITTEST_FRAMEWORK}"
+ "-DMatlab_ADDITIONNAL_STARTUP_OPTIONS=${${prefix}_MATLAB_ADDITIONAL_STARTUP_OPTIONS}"
+ "-Dunittest_file_to_run=${${prefix}_UNITTEST_FILE}"
+ "-Dcustom_Matlab_test_command=${${prefix}_CUSTOM_TEST_COMMAND}"
+ "-Dcmd_to_run_before_test=${${prefix}_UNITTEST_PRECOMMAND}"
-P ${_FindMatlab_SELF_DIR}/MatlabTestsRedirect.cmake
${${prefix}_TEST_ARGS}
${${prefix}_UNPARSED_ARGUMENTS}
@@ -1034,7 +1055,7 @@ function(_Matlab_get_version_from_root matlab_root matlab_known_version matlab_f
if(${list_of_all_versions_length} GREATER 0)
list(GET matlab_list_of_all_versions 0 _matlab_version_tmp)
else()
- set(_matlab_version_tmp "")
+ set(_matlab_version_tmp "unknown")
endif()
# set the version into the cache
diff --git a/Modules/FindPythonInterp.cmake b/Modules/FindPythonInterp.cmake
index e194185..4d726f2 100644
--- a/Modules/FindPythonInterp.cmake
+++ b/Modules/FindPythonInterp.cmake
@@ -52,7 +52,7 @@ unset(_Python_NAMES)
set(_PYTHON1_VERSIONS 1.6 1.5)
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
-set(_PYTHON3_VERSIONS 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+set(_PYTHON3_VERSIONS 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
if(PythonInterp_FIND_VERSION)
if(PythonInterp_FIND_VERSION_COUNT GREATER 1)
diff --git a/Modules/FindPythonLibs.cmake b/Modules/FindPythonLibs.cmake
index ab92f86..d9916a1 100644
--- a/Modules/FindPythonLibs.cmake
+++ b/Modules/FindPythonLibs.cmake
@@ -84,7 +84,7 @@ set(CMAKE_FIND_FRAMEWORK LAST)
set(_PYTHON1_VERSIONS 1.6 1.5)
set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
-set(_PYTHON3_VERSIONS 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+set(_PYTHON3_VERSIONS 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
if(PythonLibs_FIND_VERSION)
if(PythonLibs_FIND_VERSION_COUNT GREATER 1)
diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake
index e33b927..bacf137 100644
--- a/Modules/GenerateExportHeader.cmake
+++ b/Modules/GenerateExportHeader.cmake
@@ -208,7 +208,7 @@ macro(_test_compiler_hidden_visibility)
if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.2")
set(GCC_TOO_OLD TRUE)
- elseif(CMAKE_COMPILER_IS_GNUC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2")
+ elseif(CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2")
set(GCC_TOO_OLD TRUE)
elseif(CMAKE_CXX_COMPILER_ID MATCHES Intel AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0")
set(_INTEL_TOO_OLD TRUE)
diff --git a/Modules/MatlabTestsRedirect.cmake b/Modules/MatlabTestsRedirect.cmake
index 0ef4c3e..76f9a53 100644
--- a/Modules/MatlabTestsRedirect.cmake
+++ b/Modules/MatlabTestsRedirect.cmake
@@ -23,11 +23,12 @@
# -DMatlab_PROGRAM=matlab_exe_location
# -DMatlab_ADDITIONNAL_STARTUP_OPTIONS=""
# -Dtest_name=name_of_the_test
+# -Dcustom_Matlab_test_command=""
# -Dcmd_to_run_before_test=""
# -Dunittest_file_to_run
# -P FindMatlab_TestsRedirect.cmake
-set(Matlab_UNIT_TESTS_CMD -nosplash -nojvm -nodesktop -nodisplay ${Matlab_ADDITIONNAL_STARTUP_OPTIONS})
+set(Matlab_UNIT_TESTS_CMD -nosplash -nodesktop -nodisplay ${Matlab_ADDITIONNAL_STARTUP_OPTIONS})
if(WIN32)
set(Matlab_UNIT_TESTS_CMD ${Matlab_UNIT_TESTS_CMD} -wait)
endif()
@@ -36,6 +37,13 @@ if(NOT test_timeout)
set(test_timeout 180)
endif()
+# If timeout is -1, then do not put a timeout on the execute_process
+if(test_timeout EQUAL -1)
+ set(test_timeout "")
+else()
+ set(test_timeout TIMEOUT ${test_timeout})
+endif()
+
if(NOT cmd_to_run_before_test)
set(cmd_to_run_before_test)
endif()
@@ -50,16 +58,30 @@ foreach(s IN LISTS additional_paths)
endif()
endforeach()
-set(unittest_to_run "runtests('${unittest_file_to_run_name}'), exit(max([ans(1,:).Failed]))")
+if(custom_Matlab_test_command)
+ set(unittest_to_run "${custom_Matlab_test_command}")
+else()
+ set(unittest_to_run "runtests('${unittest_file_to_run_name}'), exit(max([ans(1,:).Failed]))")
+endif()
+
+
if(no_unittest_framework)
set(unittest_to_run "try, ${unittest_file_to_run_name}, catch err, disp('An exception has been thrown during the execution'), disp(err), disp(err.stack), exit(1), end, exit(0)")
endif()
set(Matlab_SCRIPT_TO_RUN
- "addpath(${concat_string}), path, ${cmd_to_run_before_test}, ${unittest_to_run}"
+ "addpath(${concat_string}); ${cmd_to_run_before_test}; ${unittest_to_run}"
)
+# if the working directory is not specified then default
+# to the output_directory because the log file will go there
+# if the working_directory is specified it will override the
+# output_directory
+if(NOT working_directory)
+ set(working_directory "${output_directory}")
+endif()
-set(Matlab_LOG_FILE "${output_directory}/${test_name}.log")
+string(REPLACE "/" "_" log_file_name "${test_name}.log")
+set(Matlab_LOG_FILE "${working_directory}/${log_file_name}")
set(devnull)
if(UNIX)
@@ -69,11 +91,14 @@ elseif(WIN32)
endif()
execute_process(
- COMMAND "${Matlab_PROGRAM}" ${Matlab_UNIT_TESTS_CMD} -logfile "${test_name}.log" -r "${Matlab_SCRIPT_TO_RUN}"
+ # Do not use a full path to log file. Depend on the fact that the log file
+ # is always going to go in the working_directory. This is because matlab
+ # on unix is a shell script that does not handle spaces in the logfile path.
+ COMMAND "${Matlab_PROGRAM}" ${Matlab_UNIT_TESTS_CMD} -logfile "${log_file_name}" -r "${Matlab_SCRIPT_TO_RUN}"
RESULT_VARIABLE res
- TIMEOUT ${test_timeout}
+ ${test_timeout}
OUTPUT_QUIET # we do not want the output twice
- WORKING_DIRECTORY "${output_directory}"
+ WORKING_DIRECTORY "${working_directory}"
${devnull}
)
@@ -87,5 +112,5 @@ message("Matlab test ${name_of_the_test} output:\n${matlab_log_content}") # if w
if(NOT (res EQUAL 0))
- message( FATAL_ERROR "[MATLAB] TEST FAILED" )
+ message( FATAL_ERROR "[MATLAB] TEST FAILED Matlab returned ${res}" )
endif()
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index f5c2e52..39773e1 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -221,10 +221,14 @@ set(SRCS
cmExprLexer.cxx
cmExprParser.cxx
cmExprParserHelper.cxx
+ cmExportBuildAndroidMKGenerator.h
+ cmExportBuildAndroidMKGenerator.cxx
cmExportBuildFileGenerator.h
cmExportBuildFileGenerator.cxx
cmExportFileGenerator.h
cmExportFileGenerator.cxx
+ cmExportInstallAndroidMKGenerator.h
+ cmExportInstallAndroidMKGenerator.cxx
cmExportInstallFileGenerator.h
cmExportInstallFileGenerator.cxx
cmExportTryCompileFileGenerator.h
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index e77c982..0569e8e 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 6)
-set(CMake_VERSION_PATCH 20160912)
+set(CMake_VERSION_PATCH 20160915)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index f680612..0832820 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -108,13 +108,8 @@ std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo)
void cmCTestSVN::NoteOldRevision()
{
- // Info for root repository
- this->Repositories.push_back(SVNInfo(""));
- this->RootInfo = &(this->Repositories.back());
- // Info for the external repositories
- this->LoadExternals();
+ this->LoadRepositories();
- // Get info for all the repositories
std::list<SVNInfo>::iterator itbeg = this->Repositories.begin();
std::list<SVNInfo>::iterator itend = this->Repositories.end();
for (; itbeg != itend; itbeg++) {
@@ -134,7 +129,8 @@ void cmCTestSVN::NoteOldRevision()
void cmCTestSVN::NoteNewRevision()
{
- // Get info for the external repositories
+ this->LoadRepositories();
+
std::list<SVNInfo>::iterator itbeg = this->Repositories.begin();
std::list<SVNInfo>::iterator itend = this->Repositories.end();
for (; itbeg != itend; itbeg++) {
@@ -534,8 +530,13 @@ private:
}
};
-void cmCTestSVN::LoadExternals()
+void cmCTestSVN::LoadRepositories()
{
+ // Info for root repository
+ this->Repositories.clear();
+ this->Repositories.push_back(SVNInfo(""));
+ this->RootInfo = &(this->Repositories.back());
+
// Run "svn status" to get the list of external repositories
std::vector<const char*> svn_status;
svn_status.push_back("status");
diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h
index 6f2374d..2301b10 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -86,7 +86,7 @@ private:
SVNInfo* RootInfo;
std::string LoadInfo(SVNInfo& svninfo);
- void LoadExternals();
+ void LoadRepositories();
void LoadModifications() CM_OVERRIDE;
void LoadRevisions() CM_OVERRIDE;
void LoadRevisions(SVNInfo& svninfo);
diff --git a/Source/CursesDialog/cmCursesStandardIncludes.h b/Source/CursesDialog/cmCursesStandardIncludes.h
index 4929958..1d8d7c6 100644
--- a/Source/CursesDialog/cmCursesStandardIncludes.h
+++ b/Source/CursesDialog/cmCursesStandardIncludes.h
@@ -14,10 +14,6 @@
#include <cmConfigure.h>
-#if defined(__sun__) && defined(__GNUC__)
-#define _MSE_INT_H
-#endif
-
#if defined(__hpux)
#define _BOOL_DEFINED
#include <sys/time.h>
diff --git a/Source/CursesDialog/form/form.h b/Source/CursesDialog/form/form.h
index 1219cb5..b65a3ca 100644
--- a/Source/CursesDialog/form/form.h
+++ b/Source/CursesDialog/form/form.h
@@ -33,10 +33,6 @@
#ifndef FORM_H
#define FORM_H
-#if defined(__sun__) && defined(__GNUC__)
- #define _MSE_INT_H
-#endif
-
#include <cmFormConfigure.h>
/* figure out which curses.h to include */
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index 5b84597..14ce3f7 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -14,6 +14,7 @@
#include <QCloseEvent>
#include <QCoreApplication>
+#include <QDesktopServices>
#include <QDialogButtonBox>
#include <QDragEnterEvent>
#include <QFileDialog>
@@ -227,6 +228,8 @@ void CMakeSetupDialog::initialize()
QObject::connect(this->GenerateButton, SIGNAL(clicked(bool)), this,
SLOT(doGenerate()));
+ QObject::connect(this->OpenProjectButton, SIGNAL(clicked(bool)), this,
+ SLOT(doOpenProject()));
QObject::connect(this->BrowseSourceDirectoryButton, SIGNAL(clicked(bool)),
this, SLOT(doSourceBrowse()));
@@ -499,6 +502,26 @@ void CMakeSetupDialog::doGenerate()
this->ConfigureNeeded = true;
}
+QString CMakeSetupDialog::getProjectFilename()
+{
+ QStringList nameFilter;
+ nameFilter << "*.sln"
+ << "*.xcodeproj";
+ QDir directory(this->BinaryDirectory->currentText());
+ QStringList nlnFile = directory.entryList(nameFilter);
+
+ if (nlnFile.count() == 1) {
+ return this->BinaryDirectory->currentText() + "/" + nlnFile.at(0);
+ }
+
+ return QString();
+}
+
+void CMakeSetupDialog::doOpenProject()
+{
+ QDesktopServices::openUrl(QUrl::fromLocalFile(this->getProjectFilename()));
+}
+
void CMakeSetupDialog::closeEvent(QCloseEvent* e)
{
// prompt for close if there are unsaved changes, and we're not busy
@@ -617,6 +640,11 @@ void CMakeSetupDialog::updateBinaryDirectory(const QString& dir)
this->BinaryDirectory->setEditText(dir);
this->BinaryDirectory->blockSignals(false);
}
+ if (!this->getProjectFilename().isEmpty()) {
+ this->OpenProjectButton->setEnabled(true);
+ } else {
+ this->OpenProjectButton->setEnabled(false);
+ }
}
void CMakeSetupDialog::doBinaryBrowse()
@@ -1002,22 +1030,28 @@ void CMakeSetupDialog::enterState(CMakeSetupDialog::State s)
if (s == Interrupting) {
this->ConfigureButton->setEnabled(false);
this->GenerateButton->setEnabled(false);
+ this->OpenProjectButton->setEnabled(false);
} else if (s == Configuring) {
this->setEnabledState(false);
this->GenerateButton->setEnabled(false);
this->GenerateAction->setEnabled(false);
+ this->OpenProjectButton->setEnabled(false);
this->ConfigureButton->setText(tr("&Stop"));
} else if (s == Generating) {
this->CacheModified = false;
this->setEnabledState(false);
this->ConfigureButton->setEnabled(false);
this->GenerateAction->setEnabled(false);
+ this->OpenProjectButton->setEnabled(false);
this->GenerateButton->setText(tr("&Stop"));
} else if (s == ReadyConfigure) {
this->setEnabledState(true);
this->GenerateButton->setEnabled(true);
this->GenerateAction->setEnabled(true);
this->ConfigureButton->setEnabled(true);
+ if (!this->getProjectFilename().isEmpty()) {
+ this->OpenProjectButton->setEnabled(true);
+ }
this->ConfigureButton->setText(tr("&Configure"));
this->GenerateButton->setText(tr("&Generate"));
} else if (s == ReadyGenerate) {
@@ -1025,6 +1059,9 @@ void CMakeSetupDialog::enterState(CMakeSetupDialog::State s)
this->GenerateButton->setEnabled(true);
this->GenerateAction->setEnabled(true);
this->ConfigureButton->setEnabled(true);
+ if (!this->getProjectFilename().isEmpty()) {
+ this->OpenProjectButton->setEnabled(true);
+ }
this->ConfigureButton->setText(tr("&Configure"));
this->GenerateButton->setText(tr("&Generate"));
}
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index 2a4ea7a..992de01 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -41,6 +41,8 @@ protected slots:
void initialize();
void doConfigure();
void doGenerate();
+ QString getProjectFilename();
+ void doOpenProject();
void doInstallForCommandLine();
void doHelp();
void doAbout();
diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui
index b04bd93..8d8e0cd 100644
--- a/Source/QtDialog/CMakeSetupDialog.ui
+++ b/Source/QtDialog/CMakeSetupDialog.ui
@@ -238,6 +238,13 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QPushButton" name="OpenProjectButton">
+ <property name="text">
+ <string>Open &amp;Project</string>
+ </property>
+ </widget>
+ </item>
<item>
<widget class="QLabel" name="Generator">
<property name="text">
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
new file mode 100644
index 0000000..3247cc8
--- /dev/null
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -0,0 +1,193 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmExportBuildAndroidMKGenerator.h"
+
+#include "cmExportSet.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmTargetExport.h"
+
+cmExportBuildAndroidMKGenerator::cmExportBuildAndroidMKGenerator()
+{
+ this->LG = CM_NULLPTR;
+ this->ExportSet = CM_NULLPTR;
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportHeaderCode(
+ std::ostream& os, const std::string&)
+{
+ os << "LOCAL_PATH := $(call my-dir)\n\n";
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
+ std::ostream&, const std::string&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
+ std::ostream& os, const cmGeneratorTarget* target)
+{
+ std::string targetName = this->Namespace;
+ targetName += target->GetExportName();
+ os << "include $(CLEAR_VARS)\n";
+ os << "LOCAL_MODULE := ";
+ os << targetName << "\n";
+ os << "LOCAL_SRC_FILES := ";
+ std::string path = target->GetLocalGenerator()->ConvertToOutputFormat(
+ target->GetFullPath(), cmOutputConverter::MAKERULE);
+ os << path << "\n";
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportPropertyCode(
+ std::ostream&, const std::string&, cmGeneratorTarget const*,
+ ImportPropertyMap const&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateMissingTargetsCheckCode(
+ std::ostream&, const std::vector<std::string>&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+ const cmGeneratorTarget* target, std::ostream& os,
+ const ImportPropertyMap& properties)
+{
+ std::string config = "";
+ if (this->Configurations.size()) {
+ config = this->Configurations[0];
+ }
+ cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+ target, os, properties, cmExportBuildAndroidMKGenerator::BUILD, config);
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+ const cmGeneratorTarget* target, std::ostream& os,
+ const ImportPropertyMap& properties, GenerateType type,
+ std::string const& config)
+{
+ const bool newCMP0022Behavior =
+ target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
+ target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+ if (!newCMP0022Behavior) {
+ std::ostringstream w;
+ if (type == cmExportBuildAndroidMKGenerator::BUILD) {
+ w << "export(TARGETS ... ANDROID_MK) called with policy CMP0022";
+ } else {
+ w << "install( EXPORT_ANDROID_MK ...) called with policy CMP0022";
+ }
+ w << " set to OLD for target " << target->Target->GetName() << ". "
+ << "The export will only work with CMP0022 set to NEW.";
+ target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
+ if (!properties.empty()) {
+ os << "LOCAL_CPP_FEATURES := rtti exceptions\n";
+ for (ImportPropertyMap::const_iterator pi = properties.begin();
+ pi != properties.end(); ++pi) {
+ if (pi->first == "INTERFACE_COMPILE_OPTIONS") {
+ os << "LOCAL_CPP_FEATURES += ";
+ os << (pi->second) << "\n";
+ } else if (pi->first == "INTERFACE_LINK_LIBRARIES") {
+ // need to look at list in pi->second and see if static or shared
+ // FindTargetToLink
+ // target->GetLocalGenerator()->FindGeneratorTargetToUse()
+ // then add to LOCAL_CPPFLAGS
+ std::vector<std::string> libraries;
+ cmSystemTools::ExpandListArgument(pi->second, libraries);
+ std::string staticLibs;
+ std::string sharedLibs;
+ std::string ldlibs;
+ for (std::vector<std::string>::iterator i = libraries.begin();
+ i != libraries.end(); ++i) {
+ cmGeneratorTarget* gt =
+ target->GetLocalGenerator()->FindGeneratorTargetToUse(*i);
+ if (gt) {
+
+ if (gt->GetType() == cmState::SHARED_LIBRARY ||
+ gt->GetType() == cmState::MODULE_LIBRARY) {
+ sharedLibs += " " + *i;
+ } else {
+ staticLibs += " " + *i;
+ }
+ } else {
+ // evaluate any generator expressions with the current
+ // build type of the makefile
+ cmGeneratorExpression ge;
+ CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(*i);
+ std::string evaluated =
+ cge->Evaluate(target->GetLocalGenerator(), config);
+ bool relpath = false;
+ if (type == cmExportBuildAndroidMKGenerator::INSTALL) {
+ relpath = i->substr(0, 3) == "../";
+ }
+ // check for full path or if it already has a -l, or
+ // in the case of an install check for relative paths
+ // if it is full or a link library then use string directly
+ if (cmSystemTools::FileIsFullPath(evaluated) ||
+ evaluated.substr(0, 2) == "-l" || relpath) {
+ ldlibs += " " + evaluated;
+ // if it is not a path and does not have a -l then add -l
+ } else if (!evaluated.empty()) {
+ ldlibs += " -l" + evaluated;
+ }
+ }
+ }
+ if (!sharedLibs.empty()) {
+ os << "LOCAL_SHARED_LIBRARIES :=" << sharedLibs << "\n";
+ }
+ if (!staticLibs.empty()) {
+ os << "LOCAL_STATIC_LIBRARIES :=" << staticLibs << "\n";
+ }
+ if (!ldlibs.empty()) {
+ os << "LOCAL_EXPORT_LDLIBS :=" << ldlibs << "\n";
+ }
+ } else if (pi->first == "INTERFACE_INCLUDE_DIRECTORIES") {
+ std::string includes = pi->second;
+ std::vector<std::string> includeList;
+ cmSystemTools::ExpandListArgument(includes, includeList);
+ os << "LOCAL_EXPORT_C_INCLUDES := ";
+ std::string end;
+ for (std::vector<std::string>::iterator i = includeList.begin();
+ i != includeList.end(); ++i) {
+ os << end << *i;
+ end = "\\\n";
+ }
+ os << "\n";
+ } else {
+ os << "# " << pi->first << " " << (pi->second) << "\n";
+ }
+ }
+ }
+ switch (target->GetType()) {
+ case cmState::SHARED_LIBRARY:
+ case cmState::MODULE_LIBRARY:
+ os << "include $(PREBUILT_SHARED_LIBRARY)\n";
+ break;
+ case cmState::STATIC_LIBRARY:
+ os << "include $(PREBUILT_STATIC_LIBRARY)\n";
+ break;
+ case cmState::EXECUTABLE:
+ case cmState::UTILITY:
+ case cmState::OBJECT_LIBRARY:
+ case cmState::GLOBAL_TARGET:
+ case cmState::INTERFACE_LIBRARY:
+ case cmState::UNKNOWN_LIBRARY:
+ break;
+ }
+ os << "\n";
+}
diff --git a/Source/cmExportBuildAndroidMKGenerator.h b/Source/cmExportBuildAndroidMKGenerator.h
new file mode 100644
index 0000000..e26aba0
--- /dev/null
+++ b/Source/cmExportBuildAndroidMKGenerator.h
@@ -0,0 +1,68 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmExportBuildAndroidMKGenerator_h
+#define cmExportBuildAndroidMKGenerator_h
+
+#include "cmExportBuildFileGenerator.h"
+#include "cmListFileCache.h"
+
+class cmExportSet;
+
+/** \class cmExportBuildAndroidMKGenerator
+ * \brief Generate a file exporting targets from a build tree.
+ *
+ * cmExportBuildAndroidMKGenerator generates a file exporting targets from
+ * a build tree. This exports the targets to the Android ndk build tool
+ * makefile format for prebuilt libraries.
+ *
+ * This is used to implement the EXPORT() command.
+ */
+class cmExportBuildAndroidMKGenerator : public cmExportBuildFileGenerator
+{
+public:
+ cmExportBuildAndroidMKGenerator();
+ // this is so cmExportInstallAndroidMKGenerator can share this
+ // function as they are almost the same
+ enum GenerateType
+ {
+ BUILD,
+ INSTALL
+ };
+ static void GenerateInterfaceProperties(cmGeneratorTarget const* target,
+ std::ostream& os,
+ const ImportPropertyMap& properties,
+ GenerateType type,
+ std::string const& config);
+
+protected:
+ // Implement virtual methods from the superclass.
+ virtual void GeneratePolicyHeaderCode(std::ostream&) {}
+ virtual void GeneratePolicyFooterCode(std::ostream&) {}
+ virtual void GenerateImportHeaderCode(std::ostream& os,
+ const std::string& config = "");
+ virtual void GenerateImportFooterCode(std::ostream& os);
+ virtual void GenerateImportTargetCode(std::ostream& os,
+ const cmGeneratorTarget* target);
+ virtual void GenerateExpectedTargetsCode(std::ostream& os,
+ const std::string& expectedTargets);
+ virtual void GenerateImportPropertyCode(std::ostream& os,
+ const std::string& config,
+ cmGeneratorTarget const* target,
+ ImportPropertyMap const& properties);
+ virtual void GenerateMissingTargetsCheckCode(
+ std::ostream& os, const std::vector<std::string>& missingTargets);
+ virtual void GenerateInterfaceProperties(
+ cmGeneratorTarget const* target, std::ostream& os,
+ const ImportPropertyMap& properties);
+};
+
+#endif
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index fc62492..134a63f 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -18,6 +18,7 @@
#include <cmsys/Encoding.hxx>
#include <cmsys/RegularExpression.hxx>
+#include "cmExportBuildAndroidMKGenerator.h"
#include "cmExportBuildFileGenerator.h"
#if defined(__HAIKU__)
@@ -34,6 +35,7 @@ cmExportCommand::cmExportCommand()
, Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
, Filename(&Helper, "FILE", &ArgumentGroup)
, ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup)
+ , AndroidMKFile(&Helper, "ANDROID_MK")
{
this->ExportSet = CM_NULLPTR;
}
@@ -66,13 +68,18 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
}
std::string fname;
- if (!this->Filename.WasFound()) {
+ bool android = false;
+ if (this->AndroidMKFile.WasFound()) {
+ fname = this->AndroidMKFile.GetString();
+ android = true;
+ }
+ if (!this->Filename.WasFound() && fname.empty()) {
if (args[0] != "EXPORT") {
this->SetError("FILE <filename> option missing.");
return false;
}
fname = this->ExportSetName.GetString() + ".cmake";
- } else {
+ } else if (fname.empty()) {
// Make sure the file has a .cmake extension.
if (cmSystemTools::GetFilenameLastExtension(this->Filename.GetCString()) !=
".cmake") {
@@ -176,7 +183,12 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
}
// Setup export file generation.
- cmExportBuildFileGenerator* ebfg = new cmExportBuildFileGenerator;
+ cmExportBuildFileGenerator* ebfg = CM_NULLPTR;
+ if (android) {
+ ebfg = new cmExportBuildAndroidMKGenerator;
+ } else {
+ ebfg = new cmExportBuildFileGenerator;
+ }
ebfg->SetExportFile(fname.c_str());
ebfg->SetNamespace(this->Namespace.GetCString());
ebfg->SetAppendMode(this->Append.IsEnabled());
diff --git a/Source/cmExportCommand.h b/Source/cmExportCommand.h
index 0a149af..481d2c5 100644
--- a/Source/cmExportCommand.h
+++ b/Source/cmExportCommand.h
@@ -54,6 +54,7 @@ private:
cmCAString Namespace;
cmCAString Filename;
cmCAEnabler ExportOld;
+ cmCAString AndroidMKFile;
cmExportSet* ExportSet;
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 23c77d9..c4c7d7d 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -96,24 +96,8 @@ bool cmExportFileGenerator::GenerateImportFile()
}
std::ostream& os = *foutPtr;
- // Protect that file against use with older CMake versions.
- /* clang-format off */
- os << "# Generated by CMake\n\n";
- os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
- << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
- << "endif()\n";
- /* clang-format on */
-
- // Isolate the file policy level.
- // We use 2.6 here instead of the current version because newer
- // versions of CMake should be able to export files imported by 2.6
- // until the import format changes.
- /* clang-format off */
- os << "cmake_policy(PUSH)\n"
- << "cmake_policy(VERSION 2.6)\n";
- /* clang-format on */
-
// Start with the import file header.
+ this->GeneratePolicyHeaderCode(os);
this->GenerateImportHeaderCode(os);
// Create all the imported targets.
@@ -121,7 +105,7 @@ bool cmExportFileGenerator::GenerateImportFile()
// End with the import file footer.
this->GenerateImportFooterCode(os);
- os << "cmake_policy(POP)\n";
+ this->GeneratePolicyFooterCode(os);
return result;
}
@@ -832,6 +816,31 @@ void cmExportFileGenerator::SetImportLinkProperty(
properties[prop] = link_entries;
}
+void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os)
+{
+ // Protect that file against use with older CMake versions.
+ /* clang-format off */
+ os << "# Generated by CMake\n\n";
+ os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
+ << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
+ << "endif()\n";
+ /* clang-format on */
+
+ // Isolate the file policy level.
+ // We use 2.6 here instead of the current version because newer
+ // versions of CMake should be able to export files imported by 2.6
+ // until the import format changes.
+ /* clang-format off */
+ os << "cmake_policy(PUSH)\n"
+ << "cmake_policy(VERSION 2.6)\n";
+ /* clang-format on */
+}
+
+void cmExportFileGenerator::GeneratePolicyFooterCode(std::ostream& os)
+{
+ os << "cmake_policy(POP)\n";
+}
+
void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
const std::string& config)
{
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index 354994a..d106ab7 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -78,25 +78,28 @@ protected:
std::vector<std::string>& missingTargets);
// Methods to implement export file code generation.
- void GenerateImportHeaderCode(std::ostream& os,
- const std::string& config = "");
- void GenerateImportFooterCode(std::ostream& os);
+ virtual void GeneratePolicyHeaderCode(std::ostream& os);
+ virtual void GeneratePolicyFooterCode(std::ostream& os);
+ virtual void GenerateImportHeaderCode(std::ostream& os,
+ const std::string& config = "");
+ virtual void GenerateImportFooterCode(std::ostream& os);
void GenerateImportVersionCode(std::ostream& os);
- void GenerateImportTargetCode(std::ostream& os,
- cmGeneratorTarget const* target);
- void GenerateImportPropertyCode(std::ostream& os, const std::string& config,
- cmGeneratorTarget const* target,
- ImportPropertyMap const& properties);
- void GenerateImportedFileChecksCode(
+ virtual void GenerateImportTargetCode(std::ostream& os,
+ cmGeneratorTarget const* target);
+ virtual void GenerateImportPropertyCode(std::ostream& os,
+ const std::string& config,
+ cmGeneratorTarget const* target,
+ ImportPropertyMap const& properties);
+ virtual void GenerateImportedFileChecksCode(
std::ostream& os, cmGeneratorTarget* target,
ImportPropertyMap const& properties,
const std::set<std::string>& importedLocations);
- void GenerateImportedFileCheckLoop(std::ostream& os);
- void GenerateMissingTargetsCheckCode(
+ virtual void GenerateImportedFileCheckLoop(std::ostream& os);
+ virtual void GenerateMissingTargetsCheckCode(
std::ostream& os, const std::vector<std::string>& missingTargets);
- void GenerateExpectedTargetsCode(std::ostream& os,
- const std::string& expectedTargets);
+ virtual void GenerateExpectedTargetsCode(std::ostream& os,
+ const std::string& expectedTargets);
// Collect properties with detailed information about targets beyond
// their location on disk.
@@ -140,9 +143,9 @@ protected:
ImportPropertyMap& properties);
void PopulateCompatibleInterfaceProperties(cmGeneratorTarget* target,
ImportPropertyMap& properties);
- void GenerateInterfaceProperties(cmGeneratorTarget const* target,
- std::ostream& os,
- const ImportPropertyMap& properties);
+ virtual void GenerateInterfaceProperties(
+ cmGeneratorTarget const* target, std::ostream& os,
+ const ImportPropertyMap& properties);
void PopulateIncludeDirectoriesInterface(
cmTargetExport* target,
cmGeneratorExpression::PreprocessContext preprocessRule,
@@ -169,8 +172,8 @@ protected:
std::vector<std::string>& missingTargets,
FreeTargetsReplace replace = NoReplaceFreeTargets);
- void GenerateRequiredCMakeVersion(std::ostream& os,
- const char* versionString);
+ virtual void GenerateRequiredCMakeVersion(std::ostream& os,
+ const char* versionString);
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
new file mode 100644
index 0000000..8f815b7
--- /dev/null
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -0,0 +1,146 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmExportInstallAndroidMKGenerator.h"
+
+#include "cmAlgorithms.h"
+#include "cmExportBuildAndroidMKGenerator.h"
+#include "cmExportSet.h"
+#include "cmExportSetMap.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallExportGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmTargetExport.h"
+
+cmExportInstallAndroidMKGenerator::cmExportInstallAndroidMKGenerator(
+ cmInstallExportGenerator* iegen)
+ : cmExportInstallFileGenerator(iegen)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode(
+ std::ostream& os, const std::string&)
+{
+ std::string installDir = this->IEGen->GetDestination();
+ os << "LOCAL_PATH := $(call my-dir)\n";
+ size_t numDotDot = cmSystemTools::CountChar(installDir.c_str(), '/');
+ numDotDot += (installDir.size() > 0) ? 1 : 0;
+ std::string path;
+ for (size_t n = 0; n < numDotDot; n++) {
+ path += "/..";
+ }
+ os << "_IMPORT_PREFIX := "
+ << "$(LOCAL_PATH)" << path << "\n\n";
+ for (std::vector<cmTargetExport*>::const_iterator tei =
+ this->IEGen->GetExportSet()->GetTargetExports()->begin();
+ tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) {
+ // Collect import properties for this target.
+ cmTargetExport const* te = *tei;
+ if (te->Target->GetType() == cmState::INTERFACE_LIBRARY) {
+ continue;
+ }
+ std::string dest;
+ if (te->LibraryGenerator) {
+ dest = te->LibraryGenerator->GetDestination("");
+ }
+ if (te->ArchiveGenerator) {
+ dest = te->ArchiveGenerator->GetDestination("");
+ }
+ te->Target->Target->SetProperty("__dest", dest.c_str());
+ }
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
+ std::ostream& os, const cmGeneratorTarget* target)
+{
+ std::string targetName = this->Namespace;
+ targetName += target->GetExportName();
+ os << "include $(CLEAR_VARS)\n";
+ os << "LOCAL_MODULE := ";
+ os << targetName << "\n";
+ os << "LOCAL_SRC_FILES := $(_IMPORT_PREFIX)/";
+ os << target->Target->GetProperty("__dest") << "/";
+ std::string config = "";
+ if (this->Configurations.size()) {
+ config = this->Configurations[0];
+ }
+ os << target->GetFullName(config) << "\n";
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateExpectedTargetsCode(
+ std::ostream&, const std::string&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportPropertyCode(
+ std::ostream&, const std::string&, cmGeneratorTarget const*,
+ ImportPropertyMap const&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateMissingTargetsCheckCode(
+ std::ostream&, const std::vector<std::string>&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateInterfaceProperties(
+ cmGeneratorTarget const* target, std::ostream& os,
+ const ImportPropertyMap& properties)
+{
+ std::string config = "";
+ if (this->Configurations.size()) {
+ config = this->Configurations[0];
+ }
+ cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+ target, os, properties, cmExportBuildAndroidMKGenerator::INSTALL, config);
+}
+
+void cmExportInstallAndroidMKGenerator::LoadConfigFiles(std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportPrefix(std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateRequiredCMakeVersion(
+ std::ostream&, const char*)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::CleanupTemporaryVariables(
+ std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportedFileCheckLoop(
+ std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportedFileChecksCode(
+ std::ostream&, cmGeneratorTarget*, ImportPropertyMap const&,
+ const std::set<std::string>&)
+{
+}
+
+bool cmExportInstallAndroidMKGenerator::GenerateImportFileConfig(
+ const std::string&, std::vector<std::string>&)
+{
+ return true;
+}
diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h
new file mode 100644
index 0000000..4b9f51c
--- /dev/null
+++ b/Source/cmExportInstallAndroidMKGenerator.h
@@ -0,0 +1,72 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmExportInstallAndroidMKGenerator_h
+#define cmExportInstallAndroidMKGenerator_h
+
+#include "cmExportInstallFileGenerator.h"
+
+class cmInstallExportGenerator;
+class cmInstallTargetGenerator;
+
+/** \class cmExportInstallAndroidMKGenerator
+ * \brief Generate a file exporting targets from an install tree.
+ *
+ * cmExportInstallAndroidMKGenerator generates files exporting targets from
+ * install an installation tree. The files are placed in a temporary
+ * location for installation by cmInstallExportGenerator. The file format
+ * is for the ndk build system and is a makefile fragment specifing prebuilt
+ * libraries to the ndk build system.
+ *
+ * This is used to implement the INSTALL(EXPORT_ANDROID_MK) command.
+ */
+class cmExportInstallAndroidMKGenerator : public cmExportInstallFileGenerator
+{
+public:
+ /** Construct with the export installer that will install the
+ files. */
+ cmExportInstallAndroidMKGenerator(cmInstallExportGenerator* iegen);
+
+protected:
+ // Implement virtual methods from the superclass.
+ virtual void GeneratePolicyHeaderCode(std::ostream&) {}
+ virtual void GeneratePolicyFooterCode(std::ostream&) {}
+ virtual void GenerateImportHeaderCode(std::ostream& os,
+ const std::string& config = "");
+ virtual void GenerateImportFooterCode(std::ostream& os);
+ virtual void GenerateImportTargetCode(std::ostream& os,
+ const cmGeneratorTarget* target);
+ virtual void GenerateExpectedTargetsCode(std::ostream& os,
+ const std::string& expectedTargets);
+ virtual void GenerateImportPropertyCode(std::ostream& os,
+ const std::string& config,
+ cmGeneratorTarget const* target,
+ ImportPropertyMap const& properties);
+ virtual void GenerateMissingTargetsCheckCode(
+ std::ostream& os, const std::vector<std::string>& missingTargets);
+ virtual void GenerateInterfaceProperties(
+ cmGeneratorTarget const* target, std::ostream& os,
+ const ImportPropertyMap& properties);
+ virtual void GenerateImportPrefix(std::ostream& os);
+ virtual void LoadConfigFiles(std::ostream&);
+ virtual void GenerateRequiredCMakeVersion(std::ostream& os,
+ const char* versionString);
+ virtual void CleanupTemporaryVariables(std::ostream&);
+ virtual void GenerateImportedFileCheckLoop(std::ostream& os);
+ virtual void GenerateImportedFileChecksCode(
+ std::ostream& os, cmGeneratorTarget* target,
+ ImportPropertyMap const& properties,
+ const std::set<std::string>& importedLocations);
+ virtual bool GenerateImportFileConfig(const std::string& config,
+ std::vector<std::string>&);
+};
+
+#endif
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index bcadaa0..f47038f 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -75,58 +75,8 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->GenerateExpectedTargetsCode(os, expectedTargets);
}
- // Set an _IMPORT_PREFIX variable for import location properties
- // to reference if they are relative to the install prefix.
- std::string installPrefix =
- this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition(
- "CMAKE_INSTALL_PREFIX");
- std::string const& expDest = this->IEGen->GetDestination();
- if (cmSystemTools::FileIsFullPath(expDest)) {
- // The export file is being installed to an absolute path so the
- // package is not relocatable. Use the configured install prefix.
- /* clang-format off */
- os <<
- "# The installation prefix configured by this project.\n"
- "set(_IMPORT_PREFIX \"" << installPrefix << "\")\n"
- "\n";
- /* clang-format on */
- } else {
- // Add code to compute the installation prefix relative to the
- // import file location.
- std::string absDest = installPrefix + "/" + expDest;
- std::string absDestS = absDest + "/";
- os << "# Compute the installation prefix relative to this file.\n"
- << "get_filename_component(_IMPORT_PREFIX"
- << " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
- if (cmHasLiteralPrefix(absDestS.c_str(), "/lib/") ||
- cmHasLiteralPrefix(absDestS.c_str(), "/lib64/") ||
- cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib/") ||
- cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib64/")) {
- // Handle "/usr move" symlinks created by some Linux distros.
- /* clang-format off */
- os <<
- "# Use original install prefix when loaded through a\n"
- "# cross-prefix symbolic link such as /lib -> /usr/lib.\n"
- "get_filename_component(_realCurr \"${_IMPORT_PREFIX}\" REALPATH)\n"
- "get_filename_component(_realOrig \"" << absDest << "\" REALPATH)\n"
- "if(_realCurr STREQUAL _realOrig)\n"
- " set(_IMPORT_PREFIX \"" << absDest << "\")\n"
- "endif()\n"
- "unset(_realOrig)\n"
- "unset(_realCurr)\n";
- /* clang-format on */
- }
- std::string dest = expDest;
- while (!dest.empty()) {
- os << "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" "
- "PATH)\n";
- dest = cmSystemTools::GetFilenamePath(dest);
- }
- os << "if(_IMPORT_PREFIX STREQUAL \"/\")\n"
- << " set(_IMPORT_PREFIX \"\")\n"
- << "endif()\n"
- << "\n";
- }
+ // Compute the relative import prefix for the file
+ this->GenerateImportPrefix(os);
std::vector<std::string> missingTargets;
@@ -204,24 +154,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->GenerateRequiredCMakeVersion(os, "2.8.12");
}
- // Now load per-configuration properties for them.
- /* clang-format off */
- os << "# Load information for each installed configuration.\n"
- << "get_filename_component(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
- << "file(GLOB CONFIG_FILES \"${_DIR}/"
- << this->GetConfigImportFileGlob() << "\")\n"
- << "foreach(f ${CONFIG_FILES})\n"
- << " include(${f})\n"
- << "endforeach()\n"
- << "\n";
- /* clang-format on */
+ this->LoadConfigFiles(os);
- // Cleanup the import prefix variable.
- /* clang-format off */
- os << "# Cleanup temporary variables.\n"
- << "set(_IMPORT_PREFIX)\n"
- << "\n";
- /* clang-format on */
+ this->CleanupTemporaryVariables(os);
this->GenerateImportedFileCheckLoop(os);
bool result = true;
@@ -242,6 +177,86 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
return result;
}
+void cmExportInstallFileGenerator::GenerateImportPrefix(std::ostream& os)
+{
+ // Set an _IMPORT_PREFIX variable for import location properties
+ // to reference if they are relative to the install prefix.
+ std::string installPrefix =
+ this->IEGen->GetLocalGenerator()->GetMakefile()->GetSafeDefinition(
+ "CMAKE_INSTALL_PREFIX");
+ std::string const& expDest = this->IEGen->GetDestination();
+ if (cmSystemTools::FileIsFullPath(expDest)) {
+ // The export file is being installed to an absolute path so the
+ // package is not relocatable. Use the configured install prefix.
+ /* clang-format off */
+ os <<
+ "# The installation prefix configured by this project.\n"
+ "set(_IMPORT_PREFIX \"" << installPrefix << "\")\n"
+ "\n";
+ /* clang-format on */
+ } else {
+ // Add code to compute the installation prefix relative to the
+ // import file location.
+ std::string absDest = installPrefix + "/" + expDest;
+ std::string absDestS = absDest + "/";
+ os << "# Compute the installation prefix relative to this file.\n"
+ << "get_filename_component(_IMPORT_PREFIX"
+ << " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
+ if (cmHasLiteralPrefix(absDestS.c_str(), "/lib/") ||
+ cmHasLiteralPrefix(absDestS.c_str(), "/lib64/") ||
+ cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib/") ||
+ cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib64/")) {
+ // Handle "/usr move" symlinks created by some Linux distros.
+ /* clang-format off */
+ os <<
+ "# Use original install prefix when loaded through a\n"
+ "# cross-prefix symbolic link such as /lib -> /usr/lib.\n"
+ "get_filename_component(_realCurr \"${_IMPORT_PREFIX}\" REALPATH)\n"
+ "get_filename_component(_realOrig \"" << absDest << "\" REALPATH)\n"
+ "if(_realCurr STREQUAL _realOrig)\n"
+ " set(_IMPORT_PREFIX \"" << absDest << "\")\n"
+ "endif()\n"
+ "unset(_realOrig)\n"
+ "unset(_realCurr)\n";
+ /* clang-format on */
+ }
+ std::string dest = expDest;
+ while (!dest.empty()) {
+ os << "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" "
+ "PATH)\n";
+ dest = cmSystemTools::GetFilenamePath(dest);
+ }
+ os << "if(_IMPORT_PREFIX STREQUAL \"/\")\n"
+ << " set(_IMPORT_PREFIX \"\")\n"
+ << "endif()\n"
+ << "\n";
+ }
+}
+
+void cmExportInstallFileGenerator::CleanupTemporaryVariables(std::ostream& os)
+{
+ /* clang-format off */
+ os << "# Cleanup temporary variables.\n"
+ << "set(_IMPORT_PREFIX)\n"
+ << "\n";
+ /* clang-format on */
+}
+
+void cmExportInstallFileGenerator::LoadConfigFiles(std::ostream& os)
+{
+ // Now load per-configuration properties for them.
+ /* clang-format off */
+ os << "# Load information for each installed configuration.\n"
+ << "get_filename_component(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
+ << "file(GLOB CONFIG_FILES \"${_DIR}/"
+ << this->GetConfigImportFileGlob() << "\")\n"
+ << "foreach(f ${CONFIG_FILES})\n"
+ << " include(${f})\n"
+ << "endforeach()\n"
+ << "\n";
+ /* clang-format on */
+}
+
void cmExportInstallFileGenerator::ReplaceInstallPrefix(std::string& input)
{
std::string::size_type pos = 0;
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index c693dc1..63f2d40 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -80,9 +80,17 @@ protected:
std::vector<std::string> FindNamespaces(cmGlobalGenerator* gg,
const std::string& name);
+ /** Generate the relative import prefix. */
+ virtual void GenerateImportPrefix(std::ostream&);
+
+ /** Generate the relative import prefix. */
+ virtual void LoadConfigFiles(std::ostream&);
+
+ virtual void CleanupTemporaryVariables(std::ostream&);
+
/** Generate a per-configuration file for the targets. */
- bool GenerateImportFileConfig(const std::string& config,
- std::vector<std::string>& missingTargets);
+ virtual bool GenerateImportFileConfig(
+ const std::string& config, std::vector<std::string>& missingTargets);
/** Fill in properties indicating installed file locations. */
void SetImportLocationProperty(const std::string& config,
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index a0aefb8..6c31481 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -77,9 +77,8 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
- cmTarget dummyHead;
- dummyHead.SetType(cmState::EXECUTABLE, "try_compile_dummy_exe");
- dummyHead.SetMakefile(tgt->Target->GetMakefile());
+ cmTarget dummyHead("try_compile_dummy_exe", cmState::EXECUTABLE,
+ cmTarget::VisibilityNormal, tgt->Target->GetMakefile());
cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator());
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 835b118..2c226cd 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -2481,6 +2481,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
std::string hashMatchMSG;
CM_AUTO_PTR<cmCryptoHash> hash;
bool showProgress = false;
+ std::string userpwd;
while (i != args.end()) {
if (*i == "TIMEOUT") {
@@ -2564,6 +2565,18 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
return false;
}
hashMatchMSG = algo + " hash";
+ } else if (*i == "USERPWD") {
+ ++i;
+ if (i == args.end()) {
+ this->SetError("DOWNLOAD missing string for USERPWD.");
+ return false;
+ }
+ userpwd = *i;
+ } else {
+ // Do not return error for compatibility reason.
+ std::string err = "Unexpected argument: ";
+ err += *i;
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, err.c_str());
}
++i;
}
@@ -2698,6 +2711,11 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
check_curl_result(res, "DOWNLOAD cannot set progress data: ");
}
+ if (!userpwd.empty()) {
+ res = ::curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
+ check_curl_result(res, "DOWNLOAD cannot set user password: ");
+ }
+
res = ::curl_easy_perform(curl);
/* always cleanup */
@@ -2778,6 +2796,7 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
std::string logVar;
std::string statusVar;
bool showProgress = false;
+ std::string userpwd;
while (i != args.end()) {
if (*i == "TIMEOUT") {
@@ -2812,6 +2831,18 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
statusVar = *i;
} else if (*i == "SHOW_PROGRESS") {
showProgress = true;
+ } else if (*i == "USERPWD") {
+ ++i;
+ if (i == args.end()) {
+ this->SetError("UPLOAD missing string for USERPWD.");
+ return false;
+ }
+ userpwd = *i;
+ } else {
+ // Do not return error for compatibility reason.
+ std::string err = "Unexpected argument: ";
+ err += *i;
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, err.c_str());
}
++i;
@@ -2920,6 +2951,11 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
::curl_easy_setopt(curl, CURLOPT_INFILESIZE, static_cast<long>(file_size));
check_curl_result(res, "UPLOAD cannot set input file size: ");
+ if (!userpwd.empty()) {
+ res = ::curl_easy_setopt(curl, CURLOPT_USERPWD, userpwd.c_str());
+ check_curl_result(res, "UPLOAD cannot set user password: ");
+ }
+
res = ::curl_easy_perform(curl);
/* always cleanup */
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 7dd8e7f..4f8c036 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -1280,11 +1280,11 @@ bool cmGeneratorTarget::HasMacOSXRpathInstallNameDir(
if (!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG")) {
std::ostringstream w;
- w << "Attempting to use";
+ w << "Attempting to use ";
if (macosx_rpath) {
- w << " MACOSX_RPATH";
+ w << "MACOSX_RPATH";
} else {
- w << " @rpath";
+ w << "@rpath";
}
w << " without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being set.";
w << " This could be because you are using a Mac OS X version";
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index ef8266f..e85d80e 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1068,8 +1068,8 @@ void cmGlobalGenerator::Configure()
cmTargets* targets = &(mf->GetTargets());
cmTargets::iterator tit;
for (tit = globalTargets.begin(); tit != globalTargets.end(); ++tit) {
- (*targets)[tit->first] = tit->second;
- (*targets)[tit->first].SetMakefile(mf);
+ targets->insert(
+ cmTargets::value_type(tit->first, tit->second.CopyForDirectory(mf)));
}
}
@@ -2101,9 +2101,12 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
}
}
if (cmSystemTools::FileExists(configFile.c_str())) {
- (*targets)[this->GetPackageTargetName()] = this->CreateGlobalTarget(
- this->GetPackageTargetName(), "Run CPack packaging tool...",
- &cpackCommandLines, depends, workingDir.c_str(), /*uses_terminal*/ true);
+ targets->insert(cmTargets::value_type(
+ this->GetPackageTargetName(),
+ this->CreateGlobalTarget(this->GetPackageTargetName(),
+ "Run CPack packaging tool...",
+ &cpackCommandLines, depends, workingDir.c_str(),
+ /*uses_terminal*/ true)));
}
// CPack source
const char* packageSourceTargetName = this->GetPackageSourceTargetName();
@@ -2122,10 +2125,12 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
if (cmSystemTools::FileExists(configFile.c_str())) {
singleLine.push_back(configFile);
cpackCommandLines.push_back(singleLine);
- (*targets)[packageSourceTargetName] = this->CreateGlobalTarget(
- packageSourceTargetName, "Run CPack packaging tool for source...",
- &cpackCommandLines, depends, workingDir.c_str(),
- /*uses_terminal*/ true);
+ targets->insert(cmTargets::value_type(
+ packageSourceTargetName,
+ this->CreateGlobalTarget(
+ packageSourceTargetName, "Run CPack packaging tool for source...",
+ &cpackCommandLines, depends, workingDir.c_str(),
+ /*uses_terminal*/ true)));
}
}
@@ -2146,10 +2151,11 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
singleLine.push_back("$(ARGS)");
}
cpackCommandLines.push_back(singleLine);
- (*targets)[this->GetTestTargetName()] =
+ targets->insert(cmTargets::value_type(
+ this->GetTestTargetName(),
this->CreateGlobalTarget(this->GetTestTargetName(), "Running tests...",
&cpackCommandLines, depends, CM_NULLPTR,
- /*uses_terminal*/ true);
+ /*uses_terminal*/ true)));
}
// Edit Cache
@@ -2167,18 +2173,22 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
cpackCommandLines.push_back(singleLine);
- (*targets)[editCacheTargetName] = this->CreateGlobalTarget(
- editCacheTargetName, "Running CMake cache editor...",
- &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ true);
+ targets->insert(cmTargets::value_type(
+ editCacheTargetName,
+ this->CreateGlobalTarget(
+ editCacheTargetName, "Running CMake cache editor...",
+ &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ true)));
} else {
singleLine.push_back(cmSystemTools::GetCMakeCommand());
singleLine.push_back("-E");
singleLine.push_back("echo");
singleLine.push_back("No interactive CMake dialog available.");
cpackCommandLines.push_back(singleLine);
- (*targets)[editCacheTargetName] = this->CreateGlobalTarget(
- editCacheTargetName, "No interactive CMake dialog available...",
- &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ false);
+ targets->insert(cmTargets::value_type(
+ editCacheTargetName,
+ this->CreateGlobalTarget(
+ editCacheTargetName, "No interactive CMake dialog available...",
+ &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ false)));
}
}
@@ -2193,9 +2203,11 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
cpackCommandLines.push_back(singleLine);
- (*targets)[rebuildCacheTargetName] = this->CreateGlobalTarget(
- rebuildCacheTargetName, "Running CMake to regenerate build system...",
- &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ true);
+ targets->insert(cmTargets::value_type(
+ rebuildCacheTargetName,
+ this->CreateGlobalTarget(
+ rebuildCacheTargetName, "Running CMake to regenerate build system...",
+ &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ true)));
}
// Install
@@ -2219,9 +2231,11 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
ostr << "Only default component available";
}
singleLine.push_back(ostr.str());
- (*targets)["list_install_components"] = this->CreateGlobalTarget(
- "list_install_components", ostr.str().c_str(), &cpackCommandLines,
- depends, CM_NULLPTR, /*uses_terminal*/ false);
+ targets->insert(cmTargets::value_type(
+ "list_install_components",
+ this->CreateGlobalTarget("list_install_components", ostr.str().c_str(),
+ &cpackCommandLines, depends, CM_NULLPTR,
+ /*uses_terminal*/ false)));
}
std::string cmd = cmSystemTools::GetCMakeCommand();
cpackCommandLines.erase(cpackCommandLines.begin(),
@@ -2260,9 +2274,11 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
singleLine.push_back("-P");
singleLine.push_back("cmake_install.cmake");
cpackCommandLines.push_back(singleLine);
- (*targets)[this->GetInstallTargetName()] = this->CreateGlobalTarget(
- this->GetInstallTargetName(), "Install the project...",
- &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ true);
+ targets->insert(cmTargets::value_type(
+ this->GetInstallTargetName(),
+ this->CreateGlobalTarget(this->GetInstallTargetName(),
+ "Install the project...", &cpackCommandLines,
+ depends, CM_NULLPTR, /*uses_terminal*/ true)));
// install_local
if (const char* install_local = this->GetInstallLocalTargetName()) {
@@ -2274,9 +2290,11 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
cpackCommandLines.end());
cpackCommandLines.push_back(localCmdLine);
- (*targets)[install_local] = this->CreateGlobalTarget(
- install_local, "Installing only the local directory...",
- &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ true);
+ targets->insert(cmTargets::value_type(
+ install_local,
+ this->CreateGlobalTarget(
+ install_local, "Installing only the local directory...",
+ &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ true)));
}
// install_strip
@@ -2290,9 +2308,11 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
cpackCommandLines.end());
cpackCommandLines.push_back(stripCmdLine);
- (*targets)[install_strip] = this->CreateGlobalTarget(
- install_strip, "Installing the project stripped...",
- &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ true);
+ targets->insert(cmTargets::value_type(
+ install_strip,
+ this->CreateGlobalTarget(
+ install_strip, "Installing the project stripped...",
+ &cpackCommandLines, depends, CM_NULLPTR, /*uses_terminal*/ true)));
}
}
}
@@ -2332,8 +2352,8 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(
const char* workingDirectory, bool uses_terminal)
{
// Package
- cmTarget target;
- target.SetType(cmState::GLOBAL_TARGET, name);
+ cmTarget target(name, cmState::GLOBAL_TARGET, cmTarget::VisibilityNormal,
+ CM_NULLPTR);
target.SetProperty("EXCLUDE_FROM_ALL", "TRUE");
std::vector<std::string> no_outputs;
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 4912eac..e464bce 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -83,6 +83,8 @@ bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
return this->HandleDirectoryMode(args);
} else if (args[0] == "EXPORT") {
return this->HandleExportMode(args);
+ } else if (args[0] == "EXPORT_ANDROID_MK") {
+ return this->HandleExportAndroidMKMode(args);
}
// Unknown mode.
@@ -1097,6 +1099,100 @@ bool cmInstallCommand::HandleDirectoryMode(
return true;
}
+bool cmInstallCommand::HandleExportAndroidMKMode(
+ std::vector<std::string> const& args)
+{
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ // This is the EXPORT mode.
+ cmInstallCommandArguments ica(this->DefaultComponentName);
+ cmCAString exp(&ica.Parser, "EXPORT_ANDROID_MK");
+ cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
+ cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
+ &ica.ArgumentGroup);
+ cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
+ exp.Follows(0);
+
+ ica.ArgumentGroup.Follows(&exp);
+ std::vector<std::string> unknownArgs;
+ ica.Parse(&args, &unknownArgs);
+
+ if (!unknownArgs.empty()) {
+ // Unknown argument.
+ std::ostringstream e;
+ e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
+ this->SetError(e.str());
+ return false;
+ }
+
+ if (!ica.Finalize()) {
+ return false;
+ }
+
+ // Make sure there is a destination.
+ if (ica.GetDestination().empty()) {
+ // A destination is required.
+ std::ostringstream e;
+ e << args[0] << " given no DESTINATION!";
+ this->SetError(e.str());
+ return false;
+ }
+
+ // Check the file name.
+ std::string fname = filename.GetString();
+ if (fname.find_first_of(":/\\") != fname.npos) {
+ std::ostringstream e;
+ e << args[0] << " given invalid export file name \"" << fname << "\". "
+ << "The FILE argument may not contain a path. "
+ << "Specify the path in the DESTINATION argument.";
+ this->SetError(e.str());
+ return false;
+ }
+
+ // Check the file extension.
+ if (!fname.empty() &&
+ cmSystemTools::GetFilenameLastExtension(fname) != ".mk") {
+ std::ostringstream e;
+ e << args[0] << " given invalid export file name \"" << fname << "\". "
+ << "The FILE argument must specify a name ending in \".mk\".";
+ this->SetError(e.str());
+ return false;
+ }
+ if (fname.find_first_of(":/\\") != fname.npos) {
+ std::ostringstream e;
+ e << args[0] << " given export name \"" << exp.GetString() << "\". "
+ << "This name cannot be safely converted to a file name. "
+ << "Specify a different export name or use the FILE option to set "
+ << "a file name explicitly.";
+ this->SetError(e.str());
+ return false;
+ }
+ // Use the default name
+ if (fname.empty()) {
+ fname = "Android.mk";
+ }
+
+ cmExportSet* exportSet =
+ this->Makefile->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
+
+ cmInstallGenerator::MessageLevel message =
+ cmInstallGenerator::SelectMessageLevel(this->Makefile);
+
+ // Create the export install generator.
+ cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
+ exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
+ ica.GetConfigurations(), ica.GetComponent().c_str(), message,
+ ica.GetExcludeFromAll(), fname.c_str(), name_space.GetCString(),
+ exportOld.IsEnabled(), true);
+ this->Makefile->AddInstallGenerator(exportGenerator);
+
+ return true;
+#else
+ static_cast<void>(args);
+ this->SetError("EXPORT_ANDROID_MK not supported in bootstrap cmake");
+ return false;
+#endif
+}
+
bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
{
// This is the EXPORT mode.
@@ -1203,7 +1299,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
ica.GetConfigurations(), ica.GetComponent().c_str(), message,
ica.GetExcludeFromAll(), fname.c_str(), name_space.GetCString(),
- exportOld.IsEnabled());
+ exportOld.IsEnabled(), false);
this->Makefile->AddInstallGenerator(exportGenerator);
return true;
diff --git a/Source/cmInstallCommand.h b/Source/cmInstallCommand.h
index 3718ad5..7bc974c 100644
--- a/Source/cmInstallCommand.h
+++ b/Source/cmInstallCommand.h
@@ -48,6 +48,7 @@ private:
bool HandleFilesMode(std::vector<std::string> const& args);
bool HandleDirectoryMode(std::vector<std::string> const& args);
bool HandleExportMode(std::vector<std::string> const& args);
+ bool HandleExportAndroidMKMode(std::vector<std::string> const& args);
bool MakeFilesFullPath(const char* modeName,
const std::vector<std::string>& relFiles,
std::vector<std::string>& absFiles);
diff --git a/Source/cmInstallExportAndroidMKGenerator.cxx b/Source/cmInstallExportAndroidMKGenerator.cxx
new file mode 100644
index 0000000..43bdc01
--- /dev/null
+++ b/Source/cmInstallExportAndroidMKGenerator.cxx
@@ -0,0 +1,149 @@
+
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmInstallExportAndroidMKGenerator.h"
+
+#include <stdio.h>
+
+#include "cmExportInstallFileGenerator.h"
+#include "cmExportSet.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallFilesGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmake.h"
+
+cmInstallExportAndroidMKGenerator::cmInstallExportAndroidMKGenerator(
+ cmExportSet* exportSet, const char* destination,
+ const char* file_permissions, std::vector<std::string> const& configurations,
+ const char* component, MessageLevel message, bool exclude_from_all,
+ const char* filename, const char* name_space, bool exportOld)
+ : cmInstallExportGenerator(exportSet, destination, file_permissions,
+ configurations, component, message,
+ exclude_from_all, filename, name_space, exportOld)
+{
+}
+
+cmInstallExportAndroidMKGenerator::~cmInstallExportAndroidMKGenerator()
+{
+}
+
+void cmInstallExportAndroidMKGenerator::Compute(cmLocalGenerator* lg)
+{
+ this->LocalGenerator = lg;
+ this->ExportSet->Compute(lg);
+}
+
+void cmInstallExportAndroidMKGenerator::GenerateScript(std::ostream& os)
+{
+ // Skip empty sets.
+ if (ExportSet->GetTargetExports()->empty()) {
+ std::ostringstream e;
+ e << "INSTALL(EXPORT) given unknown export \"" << ExportSet->GetName()
+ << "\"";
+ cmSystemTools::Error(e.str().c_str());
+ return;
+ }
+
+ // Create the temporary directory in which to store the files.
+ this->ComputeTempDir();
+ cmSystemTools::MakeDirectory(this->TempDir.c_str());
+
+ // Construct a temporary location for the file.
+ this->MainImportFile = this->TempDir;
+ this->MainImportFile += "/";
+ this->MainImportFile += this->FileName;
+
+ // Generate the import file for this export set.
+ this->EFGen->SetExportFile(this->MainImportFile.c_str());
+ this->EFGen->SetNamespace(this->Namespace);
+ this->EFGen->SetExportOld(this->ExportOld);
+ if (this->ConfigurationTypes->empty()) {
+ if (!this->ConfigurationName.empty()) {
+ this->EFGen->AddConfiguration(this->ConfigurationName);
+ } else {
+ this->EFGen->AddConfiguration("");
+ }
+ } else {
+ for (std::vector<std::string>::const_iterator ci =
+ this->ConfigurationTypes->begin();
+ ci != this->ConfigurationTypes->end(); ++ci) {
+ this->EFGen->AddConfiguration(*ci);
+ }
+ }
+ this->EFGen->GenerateImportFile();
+
+ // Perform the main install script generation.
+ this->cmInstallGenerator::GenerateScript(os);
+}
+
+void cmInstallExportAndroidMKGenerator::GenerateScriptConfigs(
+ std::ostream& os, Indent const& indent)
+{
+ // Create the main install rules first.
+ this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
+
+ // Now create a configuration-specific install rule for the import
+ // file of each configuration.
+ std::vector<std::string> files;
+ for (std::map<std::string, std::string>::const_iterator i =
+ this->EFGen->GetConfigImportFiles().begin();
+ i != this->EFGen->GetConfigImportFiles().end(); ++i) {
+ files.push_back(i->second);
+ std::string config_test = this->CreateConfigTest(i->first);
+ os << indent << "if(" << config_test << ")\n";
+ this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
+ false, this->FilePermissions.c_str(), CM_NULLPTR,
+ CM_NULLPTR, CM_NULLPTR, indent.Next());
+ os << indent << "endif()\n";
+ files.clear();
+ }
+}
+
+void cmInstallExportAndroidMKGenerator::GenerateScriptActions(
+ std::ostream& os, Indent const& indent)
+{
+ // Remove old per-configuration export files if the main changes.
+ std::string installedDir = "$ENV{DESTDIR}";
+ installedDir += this->ConvertToAbsoluteDestination(this->Destination);
+ installedDir += "/";
+ std::string installedFile = installedDir;
+ installedFile += this->FileName;
+ os << indent << "if(EXISTS \"" << installedFile << "\")\n";
+ Indent indentN = indent.Next();
+ Indent indentNN = indentN.Next();
+ Indent indentNNN = indentNN.Next();
+ /* clang-format off */
+ os << indentN << "file(DIFFERENT EXPORT_FILE_CHANGED FILES\n"
+ << indentN << " \"" << installedFile << "\"\n"
+ << indentN << " \"" << this->MainImportFile << "\")\n";
+ os << indentN << "if(EXPORT_FILE_CHANGED)\n";
+ os << indentNN << "file(GLOB OLD_CONFIG_FILES \"" << installedDir
+ << this->EFGen->GetConfigImportFileGlob() << "\")\n";
+ os << indentNN << "if(OLD_CONFIG_FILES)\n";
+ os << indentNNN << "message(STATUS \"Old export file \\\"" << installedFile
+ << "\\\" will be replaced. Removing files [${OLD_CONFIG_FILES}].\")\n";
+ os << indentNNN << "file(REMOVE ${OLD_CONFIG_FILES})\n";
+ os << indentNN << "endif()\n";
+ os << indentN << "endif()\n";
+ os << indent << "endif()\n";
+ /* clang-format on */
+
+ // Install the main export file.
+ std::vector<std::string> files;
+ files.push_back(this->MainImportFile);
+ this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
+ false, this->FilePermissions.c_str(), CM_NULLPTR,
+ CM_NULLPTR, CM_NULLPTR, indent);
+}
diff --git a/Source/cmInstallExportAndroidMKGenerator.h b/Source/cmInstallExportAndroidMKGenerator.h
new file mode 100644
index 0000000..158972d
--- /dev/null
+++ b/Source/cmInstallExportAndroidMKGenerator.h
@@ -0,0 +1,46 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmInstallExportAndroidMKGenerator_h
+#define cmInstallExportAndroidMKGenerator_h
+
+#include "cmInstallExportGenerator.h"
+
+class cmExportInstallFileGenerator;
+class cmInstallFilesGenerator;
+class cmInstallTargetGenerator;
+class cmExportSet;
+class cmMakefile;
+
+/** \class cmInstallExportAndroidMKGenerator
+ * \brief Generate rules for creating an export files.
+ */
+class cmInstallExportAndroidMKGenerator : public cmInstallExportGenerator
+{
+public:
+ cmInstallExportAndroidMKGenerator(
+ cmExportSet* exportSet, const char* dest, const char* file_permissions,
+ const std::vector<std::string>& configurations, const char* component,
+ MessageLevel message, bool exclude_from_all, const char* filename,
+ const char* name_space, bool exportOld);
+ ~cmInstallExportAndroidMKGenerator();
+
+ void Compute(cmLocalGenerator* lg);
+
+protected:
+ virtual void GenerateScript(std::ostream& os);
+ virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
+ virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
+ void GenerateImportFile(cmExportSet const* exportSet);
+ void GenerateImportFile(const char* config, cmExportSet const* exportSet);
+};
+
+#endif
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index 27628f4..5ea7faf 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -16,6 +16,9 @@
#include <sstream>
#include <utility>
+#ifdef CMAKE_BUILD_WITH_CMAKE
+#include "cmExportInstallAndroidMKGenerator.h"
+#endif
#include "cmExportInstallFileGenerator.h"
#include "cmExportSet.h"
#include "cmInstallType.h"
@@ -27,7 +30,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
cmExportSet* exportSet, const char* destination,
const char* file_permissions, std::vector<std::string> const& configurations,
const char* component, MessageLevel message, bool exclude_from_all,
- const char* filename, const char* name_space, bool exportOld)
+ const char* filename, const char* name_space, bool exportOld, bool android)
: cmInstallGenerator(destination, configurations, component, message,
exclude_from_all)
, ExportSet(exportSet)
@@ -37,7 +40,13 @@ cmInstallExportGenerator::cmInstallExportGenerator(
, ExportOld(exportOld)
, LocalGenerator(CM_NULLPTR)
{
- this->EFGen = new cmExportInstallFileGenerator(this);
+ if (android) {
+#ifdef CMAKE_BUILD_WITH_CMAKE
+ this->EFGen = new cmExportInstallAndroidMKGenerator(this);
+#endif
+ } else {
+ this->EFGen = new cmExportInstallFileGenerator(this);
+ }
exportSet->AddInstallation(this);
}
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index 5539827..ac02386 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -37,7 +37,8 @@ public:
const std::vector<std::string>& configurations,
const char* component, MessageLevel message,
bool exclude_from_all, const char* filename,
- const char* name_space, bool exportOld);
+ const char* name_space, bool exportOld,
+ bool android);
~cmInstallExportGenerator() CM_OVERRIDE;
cmExportSet* GetExportSet() { return this->ExportSet; }
diff --git a/Source/cmInstallTargetsCommand.cxx b/Source/cmInstallTargetsCommand.cxx
index 056ea24..6b594b6 100644
--- a/Source/cmInstallTargetsCommand.cxx
+++ b/Source/cmInstallTargetsCommand.cxx
@@ -37,14 +37,17 @@ bool cmInstallTargetsCommand::InitialPass(std::vector<std::string> const& args,
}
runtime_dir = *s;
- } else if (tgts.find(*s) != tgts.end()) {
- tgts[*s].SetInstallPath(args[0].c_str());
- tgts[*s].SetRuntimeInstallPath(runtime_dir.c_str());
- tgts[*s].SetHaveInstallRule(true);
} else {
- std::string str = "Cannot find target: \"" + *s + "\" to install.";
- this->SetError(str);
- return false;
+ cmTargets::iterator ti = tgts.find(*s);
+ if (ti != tgts.end()) {
+ ti->second.SetInstallPath(args[0].c_str());
+ ti->second.SetRuntimeInstallPath(runtime_dir.c_str());
+ ti->second.SetHaveInstallRule(true);
+ } else {
+ std::string str = "Cannot find target: \"" + *s + "\" to install.";
+ this->SetError(str);
+ return false;
+ }
}
}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 694a9f6..a76bed3 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -175,15 +175,14 @@ void cmLocalGenerator::GenerateTestFiles()
(*gi)->Compute(this);
(*gi)->Generate(fout, config, configurationTypes);
}
- size_t i;
- std::vector<cmState::Snapshot> children =
- this->Makefile->GetStateSnapshot().GetChildren();
- for (i = 0; i < children.size(); ++i) {
+ typedef std::vector<cmState::Snapshot> vec_t;
+ vec_t const& children = this->Makefile->GetStateSnapshot().GetChildren();
+ for (vec_t::const_iterator i = children.begin(); i != children.end(); ++i) {
// TODO: Use add_subdirectory instead?
- fout << "subdirs(";
- std::string outP = children[i].GetDirectory().GetCurrentBinary();
- fout << this->ConvertToRelativePath(outP, START_OUTPUT);
- fout << ")" << std::endl;
+ std::string outP = i->GetDirectory().GetCurrentBinary();
+ outP = this->ConvertToRelativePath(outP, START_OUTPUT);
+ outP = cmOutputConverter::EscapeForCMake(outP);
+ fout << "subdirs(" << outP << ")" << std::endl;
}
}
@@ -1531,9 +1530,6 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
linkLibs += " ";
}
- // Write the library flags to the build rule.
- fout << linkLibs;
-
// Check what kind of rpath flags to use.
if (cli.GetRuntimeSep().empty()) {
// Each rpath entry gets its own option ("-R a -R b -R c")
@@ -1560,6 +1556,9 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
}
}
+ // Write the library flags to the build rule.
+ fout << linkLibs;
+
// Add the linker runtime search path if any.
std::string rpath_link = cli.GetRPathLinkString();
if (!cli.GetRPathLinkFlag().empty() && !rpath_link.empty()) {
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index e5a5e6e..508c670 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -979,8 +979,9 @@ void cmMakefile::AddCustomCommandOldStyle(
// then add the source to the target to make sure the rule is
// included.
if (sf && !sf->GetPropertyAsBool("__CMAKE_RULE")) {
- if (this->Targets.find(target) != this->Targets.end()) {
- this->Targets[target].AddSource(sf->GetFullPath());
+ cmTargets::iterator ti = this->Targets.find(target);
+ if (ti != this->Targets.end()) {
+ ti->second.AddSource(sf->GetFullPath());
} else {
cmSystemTools::Error("Attempt to add a custom rule to a target "
"that does not exist yet for target ",
@@ -1924,10 +1925,10 @@ cmTarget* cmMakefile::AddNewTarget(cmState::TargetType type,
const std::string& name)
{
cmTargets::iterator it =
- this->Targets.insert(cmTargets::value_type(name, cmTarget())).first;
- cmTarget& target = it->second;
- target.SetType(type, name);
- target.SetMakefile(this);
+ this->Targets
+ .insert(cmTargets::value_type(
+ name, cmTarget(name, type, cmTarget::VisibilityNormal, this)))
+ .first;
this->GetGlobalGenerator()->IndexTarget(&it->second);
return &it->second;
}
@@ -3709,10 +3710,10 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name,
cmState::TargetType type, bool global)
{
// Create the target.
- CM_AUTO_PTR<cmTarget> target(new cmTarget);
- target->SetType(type, name);
- target->MarkAsImported(global);
- target->SetMakefile(this);
+ CM_AUTO_PTR<cmTarget> target(
+ new cmTarget(name, type, global ? cmTarget::VisibilityImportedGlobally
+ : cmTarget::VisibilityImported,
+ this));
// Add to the set of available imported targets.
this->ImportedTargets[name] = target.get();
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 7352217..36ed614 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -2416,6 +2416,83 @@ bool cmSystemTools::VersionCompareGreaterEq(std::string const& lhs,
lhs.c_str(), rhs.c_str());
}
+static size_t cm_strverscmp_find_first_difference_or_end(const char* lhs,
+ const char* rhs)
+{
+ size_t i = 0;
+ /* Step forward until we find a difference or both strings end together.
+ The difference may lie on the null-terminator of one string. */
+ while (lhs[i] == rhs[i] && lhs[i] != 0) {
+ ++i;
+ }
+ return i;
+}
+
+static size_t cm_strverscmp_find_digits_begin(const char* s, size_t i)
+{
+ /* Step back until we are not preceded by a digit. */
+ while (i > 0 && isdigit(s[i - 1])) {
+ --i;
+ }
+ return i;
+}
+
+static size_t cm_strverscmp_find_digits_end(const char* s, size_t i)
+{
+ /* Step forward over digits. */
+ while (isdigit(s[i])) {
+ ++i;
+ }
+ return i;
+}
+
+static size_t cm_strverscmp_count_leading_zeros(const char* s, size_t b)
+{
+ size_t i = b;
+ /* Step forward over zeros that are followed by another digit. */
+ while (s[i] == '0' && isdigit(s[i + 1])) {
+ ++i;
+ }
+ return i - b;
+}
+
+static int cm_strverscmp(const char* lhs, const char* rhs)
+{
+ size_t const i = cm_strverscmp_find_first_difference_or_end(lhs, rhs);
+ if (lhs[i] != rhs[i]) {
+ /* The strings differ starting at 'i'. Check for a digit sequence. */
+ size_t const b = cm_strverscmp_find_digits_begin(lhs, i);
+ if (b != i || (isdigit(lhs[i]) && isdigit(rhs[i]))) {
+ /* A digit sequence starts at 'b', preceding or at 'i'. */
+
+ /* Look for leading zeros, implying a leading decimal point. */
+ size_t const lhs_zeros = cm_strverscmp_count_leading_zeros(lhs, b);
+ size_t const rhs_zeros = cm_strverscmp_count_leading_zeros(rhs, b);
+ if (lhs_zeros != rhs_zeros) {
+ /* The side with more leading zeros orders first. */
+ return rhs_zeros > lhs_zeros ? 1 : -1;
+ }
+ if (lhs_zeros == 0) {
+ /* No leading zeros; compare digit sequence lengths. */
+ size_t const lhs_end = cm_strverscmp_find_digits_end(lhs, i);
+ size_t const rhs_end = cm_strverscmp_find_digits_end(rhs, i);
+ if (lhs_end != rhs_end) {
+ /* The side with fewer digits orders first. */
+ return lhs_end > rhs_end ? 1 : -1;
+ }
+ }
+ }
+ }
+
+ /* Ordering was not decided by digit sequence lengths; compare bytes. */
+ return lhs[i] - rhs[i];
+}
+
+int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs)
+{
+ return cm_strverscmp(lhs.c_str(), rhs.c_str());
+}
+
bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
bool* removed)
{
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 3c1a9f4..aecf40e 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -306,6 +306,16 @@ public:
std::string const& rhs);
/**
+ * Compare two ASCII strings using natural versioning order.
+ * Non-numerical characters are compared directly.
+ * Numerical characters are first globbed such that, e.g.
+ * `test000 < test01 < test0 < test1 < test10`.
+ * Return a value less than, equal to, or greater than zero if lhs
+ * precedes, equals, or succeeds rhs in the defined ordering.
+ */
+ static int strverscmp(std::string const& lhs, std::string const& rhs);
+
+ /**
* Determine the file type based on the extension
*/
static FileFormat GetFileFormat(const char* ext);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index d5274cd..d964f00 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -59,28 +59,41 @@ public:
std::vector<cmListFileBacktrace> LinkImplementationPropertyBacktraces;
};
-cmTarget::cmTarget()
+cmTarget::cmTarget(std::string const& name, cmState::TargetType type,
+ Visibility vis, cmMakefile* mf)
{
+ assert(mf || type == cmState::GLOBAL_TARGET);
+ this->Name = name;
+ this->TargetTypeValue = type;
this->Makefile = CM_NULLPTR;
this->HaveInstallRule = false;
this->DLLPlatform = false;
this->IsAndroid = false;
- this->IsImportedTarget = false;
- this->ImportedGloballyVisible = false;
+ this->IsImportedTarget =
+ (vis == VisibilityImported || vis == VisibilityImportedGlobally);
+ this->ImportedGloballyVisible = vis == VisibilityImportedGlobally;
this->BuildInterfaceIncludesAppended = false;
-}
-void cmTarget::SetType(cmState::TargetType type, const std::string& name)
-{
- this->Name = name;
// only add dependency information for library targets
- this->TargetTypeValue = type;
if (this->TargetTypeValue >= cmState::STATIC_LIBRARY &&
this->TargetTypeValue <= cmState::MODULE_LIBRARY) {
this->RecordDependencies = true;
} else {
this->RecordDependencies = false;
}
+
+ if (mf) {
+ this->SetMakefile(mf);
+ }
+}
+
+cmTarget cmTarget::CopyForDirectory(cmMakefile* mf) const
+{
+ assert(this->GetType() == cmState::GLOBAL_TARGET);
+ assert(this->GetMakefile() == CM_NULLPTR);
+ cmTarget result(*this);
+ result.SetMakefile(mf);
+ return result;
}
void cmTarget::SetMakefile(cmMakefile* mf)
@@ -1062,12 +1075,6 @@ void cmTarget::CheckProperty(const std::string& prop,
}
}
-void cmTarget::MarkAsImported(bool global)
-{
- this->IsImportedTarget = true;
- this->ImportedGloballyVisible = global;
-}
-
bool cmTarget::HandleLocationPropertyPolicy(cmMakefile* context) const
{
if (this->IsImported()) {
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index fc30166..ebc92f3 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -63,7 +63,16 @@ private:
class cmTarget
{
public:
- cmTarget();
+ enum Visibility
+ {
+ VisibilityNormal,
+ VisibilityImported,
+ VisibilityImportedGlobally
+ };
+
+ cmTarget(std::string const& name, cmState::TargetType type, Visibility vis,
+ cmMakefile* mf);
+
enum CustomCommandType
{
PRE_BUILD,
@@ -76,18 +85,13 @@ public:
*/
cmState::TargetType GetType() const { return this->TargetTypeValue; }
- /**
- * Set the target type
- */
- void SetType(cmState::TargetType f, const std::string& name);
-
- void MarkAsImported(bool global = false);
-
///! Set/Get the name of the target
const std::string& GetName() const { return this->Name; }
- ///! Set the cmMakefile that owns this target
- void SetMakefile(cmMakefile* mf);
+ /** Get a copy of this target adapted for the given directory. */
+ cmTarget CopyForDirectory(cmMakefile* mf) const;
+
+ /** Get the cmMakefile that owns this target. */
cmMakefile* GetMakefile() const { return this->Makefile; }
#define DECLARE_TARGET_POLICY(POLICY) \
@@ -279,6 +283,8 @@ public:
};
private:
+ void SetMakefile(cmMakefile* mf);
+
bool HandleLocationPropertyPolicy(cmMakefile* context) const;
const char* GetSuffixVariableInternal(bool implib) const;
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 61b74db..a94212c 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -123,6 +123,8 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
formatString += flag;
switch (flag) {
+ case 'a':
+ case 'b':
case 'd':
case 'H':
case 'I':
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index d6bea3d..18a7894 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -35,7 +35,7 @@
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include "cmGraphVizWriter.h"
#include "cmVariableWatch.h"
-#include <cm_jsoncpp_value.h>
+
#include <cm_jsoncpp_writer.h>
#endif
@@ -233,10 +233,9 @@ cmake::~cmake()
delete this->FileComparison;
}
-std::string cmake::ReportCapabilities() const
-{
- std::string result;
#if defined(CMAKE_BUILD_WITH_CMAKE)
+Json::Value cmake::ReportCapabilitiesJson() const
+{
Json::Value obj = Json::objectValue;
// Version information:
Json::Value version = Json::objectValue;
@@ -287,8 +286,16 @@ std::string cmake::ReportCapabilities() const
#else
obj["serverMode"] = false;
#endif
+ return obj;
+}
+#endif
+
+std::string cmake::ReportCapabilities() const
+{
+ std::string result;
+#if defined(CMAKE_BUILD_WITH_CMAKE)
Json::FastWriter writer;
- result = writer.write(obj);
+ result = writer.write(this->ReportCapabilitiesJson());
#else
result = "Not supported";
#endif
@@ -1039,6 +1046,28 @@ const char* cmake::GetHomeOutputDirectory() const
return this->State->GetBinaryDirectory();
}
+std::string cmake::FindCacheFile(const std::string& binaryDir)
+{
+ std::string cachePath = binaryDir;
+ cmSystemTools::ConvertToUnixSlashes(cachePath);
+ std::string cacheFile = cachePath;
+ cacheFile += "/CMakeCache.txt";
+ if (!cmSystemTools::FileExists(cacheFile.c_str())) {
+ // search in parent directories for cache
+ std::string cmakeFiles = cachePath;
+ cmakeFiles += "/CMakeFiles";
+ if (cmSystemTools::FileExists(cmakeFiles.c_str())) {
+ std::string cachePathFound =
+ cmSystemTools::FileExistsInParentDirectories("CMakeCache.txt",
+ cachePath.c_str(), "/");
+ if (!cachePathFound.empty()) {
+ cachePath = cmSystemTools::GetFilenamePath(cachePathFound);
+ }
+ }
+ }
+ return cachePath;
+}
+
void cmake::SetGlobalGenerator(cmGlobalGenerator* gg)
{
if (!gg) {
@@ -2337,24 +2366,8 @@ int cmake::Build(const std::string& dir, const std::string& target,
std::cerr << "Error: " << dir << " is not a directory\n";
return 1;
}
- std::string cachePath = dir;
- cmSystemTools::ConvertToUnixSlashes(cachePath);
- std::string cacheFile = cachePath;
- cacheFile += "/CMakeCache.txt";
- if (!cmSystemTools::FileExists(cacheFile.c_str())) {
- // search in parent directories for cache
- std::string cmakeFiles = cachePath;
- cmakeFiles += "/CMakeFiles";
- if (cmSystemTools::FileExists(cmakeFiles.c_str())) {
- std::string cachePathFound =
- cmSystemTools::FileExistsInParentDirectories("CMakeCache.txt",
- cachePath.c_str(), "/");
- if (!cachePathFound.empty()) {
- cachePath = cmSystemTools::GetFilenamePath(cachePathFound);
- }
- }
- }
+ std::string cachePath = FindCacheFile(dir);
if (!this->LoadCache(cachePath)) {
std::cerr << "Error: could not load cache\n";
return 1;
diff --git a/Source/cmake.h b/Source/cmake.h
index 9dc429d..6095a59 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -24,6 +24,10 @@
#include <string>
#include <vector>
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+#include "cm_jsoncpp_value.h"
+#endif
+
class cmExternalMakefileProjectGeneratorFactory;
class cmFileTimeComparison;
class cmGlobalGenerator;
@@ -118,6 +122,9 @@ public:
/// Destructor
~cmake();
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+ Json::Value ReportCapabilitiesJson() const;
+#endif
std::string ReportCapabilities() const;
static const char* GetCMakeFilesDirectory() { return "/CMakeFiles"; }
@@ -186,6 +193,9 @@ public:
return this->GlobalGenerator;
}
+ ///! Return the full path to where the CMakeCache.txt file should be.
+ static std::string FindCacheFile(const std::string& binaryDir);
+
///! Return the global generator assigned to this instance of cmake
void SetGlobalGenerator(cmGlobalGenerator*);
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index c2e1d53..900bba0 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -91,9 +91,9 @@ void CMakeCommandUsage(const char* program)
<< " remove_directory dir - remove a directory and its contents\n"
<< " rename oldname newname - rename a file or directory "
"(on one volume)\n"
+ << " sleep <number>... - sleep for given number of seconds\n"
<< " tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n"
<< " - create or extract a tar or zip archive\n"
- << " sleep <number>... - sleep for given number of seconds\n"
<< " time command [args...] - run command and return elapsed time\n"
<< " touch file - touch a file.\n"
<< " touch_nocreate file - touch a file but do not create it.\n"
diff --git a/Tests/CMakeLib/testSystemTools.cxx b/Tests/CMakeLib/testSystemTools.cxx
index e834b93..5b5c8d2 100644
--- a/Tests/CMakeLib/testSystemTools.cxx
+++ b/Tests/CMakeLib/testSystemTools.cxx
@@ -19,6 +19,13 @@
std::cout << "FAILED: " << (m) << "\n"; \
failed = 1
+#define cmAssert(exp, m) \
+ if ((exp)) { \
+ cmPassed(m); \
+ } else { \
+ cmFailed(m); \
+ }
+
int testSystemTools(int /*unused*/, char* /*unused*/ [])
{
int failed = 0;
@@ -26,10 +33,67 @@ int testSystemTools(int /*unused*/, char* /*unused*/ [])
// Test cmSystemTools::UpperCase
std::string str = "abc";
std::string strupper = "ABC";
- if (cmSystemTools::UpperCase(str) == strupper) {
- cmPassed("cmSystemTools::UpperCase is working");
- } else {
- cmFailed("cmSystemTools::UpperCase is working");
+ cmAssert(cmSystemTools::UpperCase(str) == strupper,
+ "cmSystemTools::UpperCase");
+
+ // ----------------------------------------------------------------------
+ // Test cmSystemTools::strverscmp
+ cmAssert(cmSystemTools::strverscmp("", "") == 0, "strverscmp empty string");
+ cmAssert(cmSystemTools::strverscmp("abc", "") > 0,
+ "strverscmp string vs empty string");
+ cmAssert(cmSystemTools::strverscmp("abc", "abc") == 0,
+ "strverscmp same string");
+ cmAssert(cmSystemTools::strverscmp("abd", "abc") > 0,
+ "strverscmp character string");
+ cmAssert(cmSystemTools::strverscmp("abc", "abd") < 0,
+ "strverscmp symmetric");
+ cmAssert(cmSystemTools::strverscmp("12345", "12344") > 0,
+ "strverscmp natural numbers");
+ cmAssert(cmSystemTools::strverscmp("100", "99") > 0,
+ "strverscmp natural numbers different digits");
+ cmAssert(cmSystemTools::strverscmp("12345", "00345") > 0,
+ "strverscmp natural against decimal (same length)");
+ cmAssert(cmSystemTools::strverscmp("99999999999999", "99999999999991") > 0,
+ "strverscmp natural overflow");
+ cmAssert(cmSystemTools::strverscmp("00000000000009", "00000000000001") > 0,
+ "strverscmp deciaml precision");
+ cmAssert(cmSystemTools::strverscmp("a.b.c.0", "a.b.c.000") > 0,
+ "strverscmp multiple zeros");
+ cmAssert(cmSystemTools::strverscmp("lib_1.2_10", "lib_1.2_2") > 0,
+ "strverscmp last number ");
+ cmAssert(cmSystemTools::strverscmp("12lib", "2lib") > 0,
+ "strverscmp first number ");
+ cmAssert(cmSystemTools::strverscmp("02lib", "002lib") > 0,
+ "strverscmp first number decimal ");
+ cmAssert(cmSystemTools::strverscmp("10", "9a") > 0,
+ "strverscmp letter filler ");
+ cmAssert(cmSystemTools::strverscmp("000", "0001") > 0,
+ "strverscmp zero and leading zeros ");
+
+ // test sorting using standard strvercmp input
+ std::vector<std::string> testString;
+ testString.push_back("000");
+ testString.push_back("00");
+ testString.push_back("01");
+ testString.push_back("010");
+ testString.push_back("09");
+ testString.push_back("0");
+ testString.push_back("1");
+ testString.push_back("9");
+ testString.push_back("10");
+
+ // test global ordering of input strings
+ for (size_t i = 0; i < testString.size() - 1; i++) {
+ for (size_t j = i + 1; j < testString.size(); j++) {
+ if (cmSystemTools::strverscmp(testString[i], testString[j]) >= 0) {
+ cmFailed("cmSystemTools::strverscmp error in comparing strings " +
+ testString[i] + " " + testString[j]);
+ }
+ }
+ }
+
+ if (!failed) {
+ cmPassed("cmSystemTools::strverscmp working");
}
return failed;
}
diff --git a/Tests/CMakeTests/String-TIMESTAMP-MonthWeekNames.cmake b/Tests/CMakeTests/String-TIMESTAMP-MonthWeekNames.cmake
new file mode 100644
index 0000000..1cd44ff
--- /dev/null
+++ b/Tests/CMakeTests/String-TIMESTAMP-MonthWeekNames.cmake
@@ -0,0 +1,11 @@
+string(TIMESTAMP output "%a;%b")
+message("~${output}~")
+
+list(LENGTH output output_length)
+
+set(expected_output_length 2)
+
+if(NOT output_length EQUAL ${expected_output_length})
+ message(FATAL_ERROR "expected ${expected_output_length} entries in output "
+ "with all specifiers; found ${output_length}")
+endif()
diff --git a/Tests/CMakeTests/StringTest.cmake.in b/Tests/CMakeTests/StringTest.cmake.in
index aba35fe..a45b205 100644
--- a/Tests/CMakeTests/StringTest.cmake.in
+++ b/Tests/CMakeTests/StringTest.cmake.in
@@ -36,6 +36,8 @@ set(TIMESTAMP-IncompleteSpecifier-RESULT 0)
set(TIMESTAMP-IncompleteSpecifier-STDERR "~foobar%~")
set(TIMESTAMP-AllSpecifiers-RESULT 0)
set(TIMESTAMP-AllSpecifiers-STDERR "~[0-9]+(;[0-9]+)*~")
+set(TIMESTAMP-MonthWeekNames-RESULT 0)
+set(TIMESTAMP-MonthWeekNames-STDERR "~[^%]+;[^%]+~")
set(TIMESTAMP-UnixTime-RESULT 0)
set(TIMESTAMP-UnixTime-STDERR "~[1-9][0-9]+~")
@@ -60,6 +62,7 @@ check_cmake_test(String
TIMESTAMP-UnknownSpecifier
TIMESTAMP-IncompleteSpecifier
TIMESTAMP-AllSpecifiers
+ TIMESTAMP-MonthWeekNames
TIMESTAMP-UnixTime
)
diff --git a/Tests/RunCMake/AndroidMK/AndroidMK-check.cmake b/Tests/RunCMake/AndroidMK/AndroidMK-check.cmake
new file mode 100644
index 0000000..691e326
--- /dev/null
+++ b/Tests/RunCMake/AndroidMK/AndroidMK-check.cmake
@@ -0,0 +1,30 @@
+# This file does a regex file compare on the generated
+# Android.mk files from the AndroidMK test
+
+macro(compare_file_to_expected file expected_file)
+ file(READ "${file}" ANDROID_MK)
+ # clean up new lines
+ string(REGEX REPLACE "\r\n" "\n" ANDROID_MK "${ANDROID_MK}")
+ string(REGEX REPLACE "\n+$" "" ANDROID_MK "${ANDROID_MK}")
+ # read in the expected regex file
+ file(READ "${expected_file}" expected)
+ # clean up new lines
+ string(REGEX REPLACE "\r\n" "\n" expected "${expected}")
+ string(REGEX REPLACE "\n+$" "" expected "${expected}")
+ # compare the file to the expected regex and if there is not a match
+ # put an error message in RunCMake_TEST_FAILED
+ if(NOT "${ANDROID_MK}" MATCHES "${expected}")
+ set(RunCMake_TEST_FAILED
+ "${file} does not match ${expected_file}:
+
+Android.mk contents = [\n${ANDROID_MK}\n]
+Expected = [\n${expected}\n]")
+ endif()
+endmacro()
+
+compare_file_to_expected(
+"${RunCMake_BINARY_DIR}/AndroidMK-build/Android.mk"
+"${RunCMake_TEST_SOURCE_DIR}/expectedBuildAndroidMK.txt")
+compare_file_to_expected(
+"${RunCMake_BINARY_DIR}/AndroidMK-build/CMakeFiles/Export/share/ndk-modules/Android.mk"
+"${RunCMake_TEST_SOURCE_DIR}/expectedInstallAndroidMK.txt")
diff --git a/Tests/RunCMake/AndroidMK/AndroidMK.cmake b/Tests/RunCMake/AndroidMK/AndroidMK.cmake
new file mode 100644
index 0000000..ed21e58
--- /dev/null
+++ b/Tests/RunCMake/AndroidMK/AndroidMK.cmake
@@ -0,0 +1,11 @@
+project(build)
+set(CMAKE_BUILD_TYPE Debug)
+add_library(foo foo.cxx)
+add_library(car foo.cxx)
+add_library(bar foo.cxx)
+add_library(dog foo.cxx)
+target_link_libraries(foo car bar dog debug -lm)
+export(TARGETS bar dog car foo ANDROID_MK
+ ${build_BINARY_DIR}/Android.mk)
+install(TARGETS bar dog car foo DESTINATION lib EXPORT myexp)
+install(EXPORT_ANDROID_MK myexp DESTINATION share/ndk-modules)
diff --git a/Tests/RunCMake/AndroidMK/CMakeLists.txt b/Tests/RunCMake/AndroidMK/CMakeLists.txt
new file mode 100644
index 0000000..576787a
--- /dev/null
+++ b/Tests/RunCMake/AndroidMK/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.5)
+project(${RunCMake_TEST} NONE) # or languages needed
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/AndroidMK/RunCMakeTest.cmake b/Tests/RunCMake/AndroidMK/RunCMakeTest.cmake
new file mode 100644
index 0000000..786d45b
--- /dev/null
+++ b/Tests/RunCMake/AndroidMK/RunCMakeTest.cmake
@@ -0,0 +1,2 @@
+include(RunCMake)
+run_cmake(AndroidMK)
diff --git a/Tests/RunCMake/AndroidMK/expectedBuildAndroidMK.txt b/Tests/RunCMake/AndroidMK/expectedBuildAndroidMK.txt
new file mode 100644
index 0000000..def8fcb
--- /dev/null
+++ b/Tests/RunCMake/AndroidMK/expectedBuildAndroidMK.txt
@@ -0,0 +1,23 @@
+LOCAL_PATH.*call my-dir.*
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*bar
+LOCAL_SRC_FILES.*bar.*
+include.*PREBUILT_STATIC_LIBRARY.*
+.*
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*dog
+LOCAL_SRC_FILES.*.*dog.*
+include.*PREBUILT_STATIC_LIBRARY.*
+.*
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*car
+LOCAL_SRC_FILES.*.*car.*
+include.*PREBUILT_STATIC_LIBRARY.*
+.*
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*foo
+LOCAL_SRC_FILES.*.*foo.*
+LOCAL_CPP_FEATURES.*rtti exceptions
+LOCAL_STATIC_LIBRARIES.*car bar dog
+LOCAL_EXPORT_LDLIBS := -lm
+include.*PREBUILT_STATIC_LIBRARY.*
diff --git a/Tests/RunCMake/AndroidMK/expectedInstallAndroidMK.txt b/Tests/RunCMake/AndroidMK/expectedInstallAndroidMK.txt
new file mode 100644
index 0000000..1bdb308
--- /dev/null
+++ b/Tests/RunCMake/AndroidMK/expectedInstallAndroidMK.txt
@@ -0,0 +1,25 @@
+LOCAL_PATH.*call my-dir.*
+_IMPORT_PREFIX.*LOCAL_PATH./../..
+
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*bar
+LOCAL_SRC_FILES.*_IMPORT_PREFIX./lib.*bar.*
+include.*PREBUILT_STATIC_LIBRARY.*
+
+include.*CLEAR_VARS.
+LOCAL_MODULE.*dog
+LOCAL_SRC_FILES.*_IMPORT_PREFIX./lib.*dog.*
+include.*PREBUILT_STATIC_LIBRARY.*
+
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*car
+LOCAL_SRC_FILES.*_IMPORT_PREFIX./lib.*car.*
+include.*PREBUILT_STATIC_LIBRARY.*
+
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*foo
+LOCAL_SRC_FILES.*_IMPORT_PREFIX\)/lib.*foo.*
+LOCAL_CPP_FEATURES.*rtti exceptions
+LOCAL_STATIC_LIBRARIES.*car bar dog
+LOCAL_EXPORT_LDLIBS := -lm
+include.*PREBUILT_STATIC_LIBRARY.*
diff --git a/Tests/RunCMake/AndroidMK/foo.cxx b/Tests/RunCMake/AndroidMK/foo.cxx
new file mode 100644
index 0000000..3695dc9
--- /dev/null
+++ b/Tests/RunCMake/AndroidMK/foo.cxx
@@ -0,0 +1,3 @@
+void foo()
+{
+}
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index fa3d0f9..e36b2a6 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -331,6 +331,8 @@ add_RunCMake_test_group(CPack "DEB;RPM;TGZ")
# for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used
add_RunCMake_test(AutoExportDll)
+add_RunCMake_test(AndroidMK)
+
if(CMake_TEST_ANDROID_NDK OR CMake_TEST_ANDROID_STANDALONE_TOOLCHAIN)
if(NOT "${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
message(FATAL_ERROR "Android tests supported only by Makefile and Ninja generators")
diff --git a/Tests/RunCMake/file/DOWNLOAD-pass-not-set-result.txt b/Tests/RunCMake/file/DOWNLOAD-pass-not-set-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-pass-not-set-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/DOWNLOAD-pass-not-set-stderr.txt b/Tests/RunCMake/file/DOWNLOAD-pass-not-set-stderr.txt
new file mode 100644
index 0000000..2fa2731
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-pass-not-set-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at DOWNLOAD-pass-not-set.cmake:[0-9]+ \(file\):
+ file DOWNLOAD missing string for USERPWD.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/DOWNLOAD-pass-not-set.cmake b/Tests/RunCMake/file/DOWNLOAD-pass-not-set.cmake
new file mode 100644
index 0000000..61eff6d
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-pass-not-set.cmake
@@ -0,0 +1 @@
+file(DOWNLOAD "" "" USERPWD)
diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument-result.txt b/Tests/RunCMake/file/DOWNLOAD-unused-argument-result.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument-result.txt
diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument-stderr.txt b/Tests/RunCMake/file/DOWNLOAD-unused-argument-stderr.txt
new file mode 100644
index 0000000..82a78c9
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Warning \(dev\) at DOWNLOAD-unused-argument.cmake:[0-9]+ \(file\):
+ Unexpected argument: JUNK
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake
new file mode 100644
index 0000000..2e3fbe1
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument.cmake
@@ -0,0 +1,5 @@
+file(DOWNLOAD
+ "file://${CMAKE_CURRENT_SOURCE_DIR}/DOWNLOAD-unused-argument.txt"
+ "${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt"
+ JUNK
+ )
diff --git a/Tests/RunCMake/file/DOWNLOAD-unused-argument.txt b/Tests/RunCMake/file/DOWNLOAD-unused-argument.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/file/DOWNLOAD-unused-argument.txt
diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake
index 5f85bba..d8e9ce0 100644
--- a/Tests/RunCMake/file/RunCMakeTest.cmake
+++ b/Tests/RunCMake/file/RunCMakeTest.cmake
@@ -1,6 +1,10 @@
include(RunCMake)
run_cmake(DOWNLOAD-hash-mismatch)
+run_cmake(DOWNLOAD-unused-argument)
+run_cmake(DOWNLOAD-pass-not-set)
+run_cmake(UPLOAD-unused-argument)
+run_cmake(UPLOAD-pass-not-set)
run_cmake(INSTALL-DIRECTORY)
run_cmake(INSTALL-MESSAGE-bad)
run_cmake(FileOpenFailRead)
diff --git a/Tests/RunCMake/file/UPLOAD-pass-not-set-result.txt b/Tests/RunCMake/file/UPLOAD-pass-not-set-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-pass-not-set-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/file/UPLOAD-pass-not-set-stderr.txt b/Tests/RunCMake/file/UPLOAD-pass-not-set-stderr.txt
new file mode 100644
index 0000000..089c0ad
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-pass-not-set-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at UPLOAD-pass-not-set.cmake:[0-9]+ \(file\):
+ file UPLOAD missing string for USERPWD.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/file/UPLOAD-pass-not-set.cmake b/Tests/RunCMake/file/UPLOAD-pass-not-set.cmake
new file mode 100644
index 0000000..4f3d86c
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-pass-not-set.cmake
@@ -0,0 +1 @@
+file(UPLOAD "" "" USERPWD)
diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument-result.txt b/Tests/RunCMake/file/UPLOAD-unused-argument-result.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-unused-argument-result.txt
diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument-stderr.txt b/Tests/RunCMake/file/UPLOAD-unused-argument-stderr.txt
new file mode 100644
index 0000000..3c1b744
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-unused-argument-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Warning \(dev\) at UPLOAD-unused-argument.cmake:[0-9]+ \(file\):
+ Unexpected argument: JUNK
+Call Stack \(most recent call first\):
+ CMakeLists.txt:[0-9]+ \(include\)
+This warning is for project developers. Use -Wno-dev to suppress it.$
diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument.cmake b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake
new file mode 100644
index 0000000..94ac9ac
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-unused-argument.cmake
@@ -0,0 +1,5 @@
+file(UPLOAD
+ "${CMAKE_CURRENT_SOURCE_DIR}/UPLOAD-unused-argument.txt"
+ "file://${CMAKE_CURRENT_BINARY_DIR}/unused-argument.txt"
+ JUNK
+ )
diff --git a/Tests/RunCMake/file/UPLOAD-unused-argument.txt b/Tests/RunCMake/file/UPLOAD-unused-argument.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/file/UPLOAD-unused-argument.txt