diff options
137 files changed, 2040 insertions, 706 deletions
diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index bd55e24..21236fa 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -140,21 +140,40 @@ If ``NO_DEFAULT_PATH`` is not specified, the search process is as follows: |prefix_XXX_SUBDIR| for each ``<prefix>`` in :variable:`CMAKE_SYSTEM_PREFIX_PATH` -1. .. versionadded:: 3.12 - If called from within a find module or any other script loaded by a call to - :command:`find_package(<PackageName>)`, search prefixes unique to the - current package being found. Specifically, look in the - :variable:`<PackageName>_ROOT` CMake variable and the - :envvar:`<PackageName>_ROOT` environment variable. - The package root variables are maintained as a stack, so if called from - nested find modules or config packages, root paths from the parent's find - module or config package will be searched after paths from the current - module or package. In other words, the search order would be - ``<CurrentPackage>_ROOT``, ``ENV{<CurrentPackage>_ROOT}``, - ``<ParentPackage>_ROOT``, ``ENV{<ParentPackage>_ROOT}``, etc. - This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting - the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``. - See policy :policy:`CMP0074`. +1. If called from within a find module or any other script loaded by a call to + :command:`find_package(<PackageName>)`, search prefixes unique to the + current package being found. See policy :policy:`CMP0074`. + + .. versionadded:: 3.12 + + Specifically, search paths specified by the following variables, in order: + + a. :variable:`<PackageName>_ROOT` CMake variable, + where ``<PackageName>`` is the case-preserved package name. + + b. :variable:`<PACKAGENAME>_ROOT` CMake variable, + where ``<PACKAGENAME>`` is the upper-cased package name. + See policy :policy:`CMP0144`. + + .. versionadded:: 3.27 + + c. :envvar:`<PackageName>_ROOT` environment variable, + where ``<PackageName>`` is the case-preserved package name. + + d. :envvar:`<PACKAGENAME>_ROOT` environment variable, + where ``<PACKAGENAME>`` is the upper-cased package name. + See policy :policy:`CMP0144`. + + .. versionadded:: 3.27 + + The package root variables are maintained as a stack, so if called from + nested find modules or config packages, root paths from the parent's find + module or config package will be searched after paths from the current + module or package. In other words, the search order would be + ``<CurrentPackage>_ROOT``, ``ENV{<CurrentPackage>_ROOT}``, + ``<ParentPackage>_ROOT``, ``ENV{<ParentPackage>_ROOT}``, etc. + This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting + the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``. * |FIND_PACKAGE_ROOT_PREFIX_PATH_XXX| diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index de4cb88..b82088e 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -367,17 +367,37 @@ The set of installation prefixes is constructed using the following steps. If ``NO_DEFAULT_PATH`` is specified all ``NO_*`` options are enabled. -1. .. versionadded:: 3.12 - Search paths specified in the :variable:`<PackageName>_ROOT` CMake - variable and the :envvar:`<PackageName>_ROOT` environment variable, - where ``<PackageName>`` is the package to be found - (the case-preserved first argument to ``find_package``). - The package root variables are maintained as a stack so if - called from within a find module, root paths from the parent's find - module will also be searched after paths for the current package. - This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting - the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``. - See policy :policy:`CMP0074`. +1. Search prefixes unique to the current ``<PackageName>`` being found. + See policy :policy:`CMP0074`. + + .. versionadded:: 3.12 + + Specifically, search prefixes specified by the following variables, + in order: + + a. :variable:`<PackageName>_ROOT` CMake variable, + where ``<PackageName>`` is the case-preserved package name. + + b. :variable:`<PACKAGENAME>_ROOT` CMake variable, + where ``<PACKAGENAME>`` is the upper-cased package name. + See policy :policy:`CMP0144`. + + .. versionadded:: 3.27 + + c. :envvar:`<PackageName>_ROOT` environment variable, + where ``<PackageName>`` is the case-preserved package name. + + d. :envvar:`<PACKAGENAME>_ROOT` environment variable, + where ``<PACKAGENAME>`` is the upper-cased package name. + See policy :policy:`CMP0144`. + + .. versionadded:: 3.27 + + The package root variables are maintained as a stack so if + called from within a find module, root paths from the parent's find + module will also be searched after paths for the current package. + This can be skipped if ``NO_PACKAGE_ROOT_PATH`` is passed or by setting + the :variable:`CMAKE_FIND_USE_PACKAGE_ROOT_PATH` to ``FALSE``. 2. Search paths specified in cmake-specific cache variables. These are intended to be used on the command line with a :option:`-DVAR=VALUE <cmake -D>`. diff --git a/Help/envvar/PackageName_ROOT.rst b/Help/envvar/PackageName_ROOT.rst index fa8c385..6e9c744 100644 --- a/Help/envvar/PackageName_ROOT.rst +++ b/Help/envvar/PackageName_ROOT.rst @@ -17,3 +17,17 @@ by ``:`` on UNIX or ``;`` on Windows (the same as the ``PATH`` environment variable convention on those platforms). See also the :variable:`<PackageName>_ROOT` CMake variable. + +.. envvar:: <PACKAGENAME>_ROOT + + .. versionadded:: 3.27 + + Calls to :command:`find_package(<PackageName>)` will also search in + prefixes specified by the upper-case ``<PACKAGENAME>_ROOT`` environment + variable. See policy :policy:`CMP0144`. + +.. note:: + + Note that the ``<PackageName>_ROOT`` and ``<PACKAGENAME>_ROOT`` + environment variables are distinct only on platforms that have + case-sensitive environments. diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst index 3dac68a..37b0668 100644 --- a/Help/guide/tutorial/A Basic Starting Point.rst +++ b/Help/guide/tutorial/A Basic Starting Point.rst @@ -160,7 +160,7 @@ The last command to call for a basic project is :name: CMakeLists.txt-add_executable :language: cmake :start-after: # add the executable - :end-before: # TODO 9: + :end-before: # TODO 3: .. raw:: html @@ -240,7 +240,7 @@ the following: :name: tutorial.cxx-cxx11 :language: c++ :start-after: // convert input to double - :end-before: // TODO 12: + :end-before: // TODO 6: .. raw:: html @@ -265,7 +265,7 @@ add the :variable:`CMAKE_CXX_STANDARD` declarations above the call to :name: CMakeLists.txt-CXX_STANDARD :language: cmake :start-after: # specify the C++ standard - :end-before: # TODO 7: + :end-before: # configure a header file .. raw:: html @@ -375,7 +375,7 @@ specified CMake variables replaced: :name: CMakeLists.txt-configure_file :language: cmake :start-after: # to the source code - :end-before: # TODO 8: + :end-before: # TODO 2: .. raw:: html @@ -420,7 +420,6 @@ be replaced with the corresponding version numbers from the project in :caption: TODO 10: TutorialConfig.h.in :name: TutorialConfig.h.in :language: c++ - :end-before: // TODO 13: .. raw:: html diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst index 6f9714e..08f3eea 100644 --- a/Help/guide/tutorial/Adding Generator Expressions.rst +++ b/Help/guide/tutorial/Adding Generator Expressions.rst @@ -299,7 +299,7 @@ condition. The resulting full code looks like the following: :name: CMakeLists.txt-target_compile_options-genex :language: cmake :start-after: set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") - :end-before: # should we use our own math functions + :end-before: # configure a header file to pass some of the CMake settings .. raw:: html diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst index b69abd2..b314773 100644 --- a/Help/guide/tutorial/Adding System Introspection.rst +++ b/Help/guide/tutorial/Adding System Introspection.rst @@ -119,7 +119,7 @@ our source code can tell what resources are available. If both ``log`` and :name: MathFunctions/CMakeLists.txt-target_compile_definitions :language: cmake :start-after: # add compile definitions - :end-before: # install libs + :end-before: # state .. raw:: html @@ -136,7 +136,8 @@ Since we may be using ``log`` and ``exp``, we need to modify :caption: TODO 4: MathFunctions/mysqrt.cxx :name: MathFunctions/mysqrt.cxx-include-cmath :language: c++ - :end-before: #include <iostream> + :start-after: #include "mysqrt.h" + :end-before: include <iostream> .. raw:: html diff --git a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst index 4aef050..74b7496 100644 --- a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst +++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst @@ -100,7 +100,7 @@ follows: :name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE :language: cmake :start-after: # to find MathFunctions.h - :end-before: # TODO 3: Link to + :end-before: option .. raw:: html @@ -119,7 +119,7 @@ safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level :name: CMakeLists.txt-remove-EXTRA_INCLUDES :language: cmake :start-after: # add the MathFunctions library - :end-before: # add the executable + :end-before: # TODO 2: Link to tutorial_compiler_flags .. raw:: html diff --git a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst index b1f9840..9e6311e 100644 --- a/Help/guide/tutorial/Adding a Custom Command and Generated File.rst +++ b/Help/guide/tutorial/Adding a Custom Command and Generated File.rst @@ -23,15 +23,25 @@ The next step is to add the appropriate commands to the then run it as part of the build process. A few commands are needed to accomplish this. -First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for -``MakeTable`` is added as any other executable would be added. +First, in the ``USE_MYMATH`` section of ``MathFunctions/CMakeLists.txt``, +we add an executable for ``MakeTable``. .. literalinclude:: Step9/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_executable-MakeTable :language: cmake :start-after: # first we add the executable that generates the table - :end-before: # add the command to generate the source code + :end-before: target_link_libraries + +After creating the executable, we add the ``tutorial_compiler_flags`` to our +executable using :command:`target_link_libraries`. + +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-link-tutorial-compiler-flags + :language: cmake + :start-after: add_executable + :end-before: # add the command to generate Then we add a custom command that specifies how to produce ``Table.h`` by running MakeTable. @@ -41,7 +51,7 @@ by running MakeTable. :name: MathFunctions/CMakeLists.txt-add_custom_command-Table.h :language: cmake :start-after: # add the command to generate the source code - :end-before: # add the main library + :end-before: # library that just does sqrt Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated file ``Table.h``. This is done by adding the generated ``Table.h`` to the list @@ -51,8 +61,8 @@ of sources for the library MathFunctions. :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_library-Table.h :language: cmake - :start-after: # add the main library - :end-before: # state that anybody linking + :start-after: # library that just does sqrt + :end-before: # state that we depend on We also have to add the current binary directory to the list of include directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. @@ -62,7 +72,19 @@ directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``. :name: MathFunctions/CMakeLists.txt-target_include_directories-Table.h :language: cmake :start-after: # state that we depend on our bin - :end-before: # install libs + :end-before: target_link_libraries + +As the last thing in our ``USE_MYMATH`` section, we need to link the our +flags onto ``SqrtLibrary`` and then link ``SqrtLibrary`` onto +``MathFunctions``. This makes the resulting ``USE_MYMATH`` section look like +the following: + +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt + :caption: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-full_USE_MYMATH-section + :language: cmake + :start-after: if (USE_MYMATH) + :end-before: endif() Now let's use the generated table. First, modify ``mysqrt.cxx`` to include ``Table.h``. Next, we can rewrite the ``mysqrt`` function to use the table: diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst index a56c327..2dd731f 100644 --- a/Help/guide/tutorial/Adding a Library.rst +++ b/Help/guide/tutorial/Adding a Library.rst @@ -51,11 +51,13 @@ then use this library instead of the standard square root function provided by the compiler. For this tutorial we will put the library into a subdirectory called -``MathFunctions``. This directory already contains a header file, -``MathFunctions.h``, and a source file ``mysqrt.cxx``. We will not need to -modify either of these files. The source file has one function called +``MathFunctions``. This directory already contains the header files +``MathFunctions.h`` and ``mysqrt.h``. Their respective source files +``MathFunctions.cxx`` and ``mysqrt.cxx`` are also provided. We will not need +to modify any of these files. ``mysqrt.cxx`` has one function called ``mysqrt`` that provides similar functionality to the compiler's ``sqrt`` -function. +function. ``MathFunctions.cxx`` contains one function ``sqrt`` which serves +to hide the implementation details of ``sqrt``. From the ``Help/guide/tutorial/Step2`` directory, start with ``TODO 1`` and complete through ``TODO 6``. @@ -91,10 +93,10 @@ Solution In the ``CMakeLists.txt`` file in the ``MathFunctions`` directory, we create a library target called ``MathFunctions`` with :command:`add_library`. The -source file for the library is passed as an argument to +source files for the library are passed as an argument to :command:`add_library`. This looks like the following line: -.. raw:: html +.. raw:: html/ <details><summary>TODO 1: Click to show/hide answer</summary> @@ -171,36 +173,40 @@ Now let's use our library. In ``tutorial.cxx``, include ``MathFunctions.h``: <details><summary>TODO 5: Click to show/hide answer</summary> -.. code-block:: c++ - :caption: TODO 5 : tutorial.cxx - :name: tutorial.cxx-include_MathFunctions.h - - #include "MathFunctions.h" +.. literalinclude:: Step3/tutorial.cxx + :caption: TODO 5: tutorial.cxx + :name: CMakeLists.txt-include-MathFunctions.h + :language: cmake + :start-after: #include <string> + :end-before: #include "TutorialConfig.h" .. raw:: html </details> -Lastly, replace ``sqrt`` with our library function ``mysqrt``. +Lastly, replace ``sqrt`` with our library function ``mathfunctions::mysqrt``. .. raw:: html <details><summary>TODO 6: Click to show/hide answer</summary> -.. code-block:: c++ - :caption: TODO 6 : tutorial.cxx - :name: tutorial.cxx-call_mysqrt - - const double outputValue = mysqrt(inputValue); +.. literalinclude:: Step3/tutorial.cxx + :caption: TODO 7: tutorial.cxx + :name: CMakeLists.txt-option + :language: cmake + :start-after: const double inputValue = std::stod(argv[1]); + :end-before: std::cout .. raw:: html </details> -Exercise 2 - Making Our Library Optional -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Exercise 2 - Adding an Option +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Now let us make the MathFunctions library optional. While for the tutorial +Now let us add an option in the MathFunctions library to allow developers to +select either the custom square root implementation or the built in standard +implementation. While for the tutorial there really isn't any need to do so, for larger projects this is a common occurrence. @@ -219,28 +225,26 @@ Helpful Resources ----------------- * :command:`if` -* :command:`list` * :command:`option` -* :command:`cmakedefine <configure_file>` +* :command:`target_compile_definitions` Files to Edit ------------- -* ``CMakeLists.txt`` -* ``tutorial.cxx`` -* ``TutorialConfig.h.in`` +* ``MathFunctions/CMakeLists.txt`` +* ``MathFunctions/MathFunctions.cxx`` Getting Started --------------- Start with the resulting files from Exercise 1. Complete ``TODO 7`` through -``TODO 13``. +``TODO 9``. First create a variable ``USE_MYMATH`` using the :command:`option` command -in the top-level ``CMakeLists.txt`` file. In that same file, use that option -to determine whether to build and use the ``MathFunctions`` library. +in ``MathFunctions/CMakeLists.txt``. In that same file, use that option +to pass a compile definition to the ``MathFunctions`` library. -Then, update ``tutorial.cxx`` and ``TutorialConfig.h.in`` to use +Then, update ``MathFunctions.cxx`` to redirect compilation based on ``USE_MYMATH``. Build and Run @@ -279,7 +283,7 @@ or ``mysqrt``? Solution -------- -The first step is to add an option to the top-level ``CMakeLists.txt`` file. +The first step is to add an option to ``MathFunctions/CMakeLists.txt``. This option will be displayed in the :manual:`cmake-gui <cmake-gui(1)>` and :manual:`ccmake <ccmake(1)>` with a default value of ``ON`` that can be changed by the user. @@ -288,172 +292,95 @@ changed by the user. <details><summary>TODO 7: Click to show/hide answer</summary> -.. literalinclude:: Step3/CMakeLists.txt - :caption: TODO 7: CMakeLists.txt - :name: CMakeLists.txt-option +.. literalinclude:: Step3/MathFunctions/CMakeLists.txt + :caption: TODO 7: MathFunctions/CMakeLists.txt + :name: CMakeLists.txt-option-library-level :language: cmake :start-after: # should we use our own math functions - :end-before: # configure a header file to pass some of the CMake settings + :end-before: if (USE_MYMATH) .. raw:: html </details> -Next, make building and linking the ``MathFunctions`` library -conditional. - -Start by creating a :command:`list` of the optional library targets for our -project. At the moment, it is just ``MathFunctions``. Let's name our list -``EXTRA_LIBS``. +Next, make building and linking our library with ``mysqrt`` function +conditional using this new option. -Similarly, we need to make a :command:`list` for the optional includes which -we will call ``EXTRA_INCLUDES``. In this list, we will ``APPEND`` the path of -the header file needed for our library. - -Next, create an :command:`if` statement which checks the value of +Create an :command:`if` statement which checks the value of ``USE_MYMATH``. Inside the :command:`if` block, put the -:command:`add_subdirectory` command from Exercise 1 with the additional -:command:`list` commands. - -When ``USE_MYMATH`` is ``ON``, the lists will be generated and will be added to -our project. When ``USE_MYMATH`` is ``OFF``, the lists stay empty. With this -strategy, we allow users to toggle ``USE_MYMATH`` to manipulate what library is -used in the build. - -The top-level CMakeLists.txt file will now look like the following: +:command:`target_compile_definitions` command with the compile +definition ``USE_MYMATH``. .. raw:: html <details><summary>TODO 8: Click to show/hide answer</summary> -.. literalinclude:: Step3/CMakeLists.txt - :caption: TODO 8: CMakeLists.txt +.. literalinclude:: Step3/MathFunctions/CMakeLists.txt + :caption: TODO 8: MathFunctions/CMakeLists.txt :name: CMakeLists.txt-USE_MYMATH :language: cmake - :start-after: # add the MathFunctions library - :end-before: # add the executable + :start-after: USE_MYMATH "Use tutorial provided math implementation" ON) .. raw:: html </details> -Now that we have these two lists, we need to update -:command:`target_link_libraries` and :command:`target_include_directories` to -use them. Changing them is fairly straightforward. - -For :command:`target_link_libraries`, we replace the written out -library names with ``EXTRA_LIBS``. This looks like the following: +The corresponding changes to the source code are fairly straightforward. +In ``MathFunctions.cxx``, we make ``USE_MYMATH`` control which square root +function is used: .. raw:: html <details><summary>TODO 9: Click to show/hide answer</summary> -.. literalinclude:: Step3/CMakeLists.txt - :caption: TODO 9: CMakeLists.txt - :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS - :language: cmake - :start-after: add_executable(Tutorial tutorial.cxx) - :end-before: # TODO 3 +.. literalinclude:: Step3/MathFunctions/MathFunctions.cxx + :caption: TODO 9: MathFunctions/MathFunctions.cxx + :name: MathFunctions-USE_MYMATH-if + :language: c++ + :start-after: which square root function should we use? + :end-before: } .. raw:: html </details> -Then, we do the same thing with :command:`target_include_directories` and -``EXTRA_INCLUDES``. +Next, we need to include ``mysqrt.h`` if ``USE_MYMATH`` is defined. .. raw:: html <details><summary>TODO 10: Click to show/hide answer</summary> -.. literalinclude:: Step3/CMakeLists.txt - :caption: TODO 10 : CMakeLists.txt - :name: CMakeLists.txt-target_link_libraries-EXTRA_INCLUDES - :language: cmake - :start-after: # so that we will find TutorialConfig.h - -.. raw:: html - - </details> - -Note that this is a classic approach when dealing with many components. We -will cover the modern approach in the Step 3 of the tutorial. - -The corresponding changes to the source code are fairly straightforward. -First, in ``tutorial.cxx``, we include the ``MathFunctions.h`` header if -``USE_MYMATH`` is defined. - -.. raw:: html - - <details><summary>TODO 11: Click to show/hide answer</summary> - -.. literalinclude:: Step3/tutorial.cxx - :caption: TODO 11 : tutorial.cxx - :name: tutorial.cxx-ifdef-include +.. literalinclude:: Step3/MathFunctions/MathFunctions.cxx + :caption: TODO 10: MathFunctions/MathFunctions.cxx + :name: MathFunctions-USE_MYMATH-if-include :language: c++ - :start-after: // should we include the MathFunctions header - :end-before: int main + :start-after: include <cmath> + :end-before: namespace mathfunctions .. raw:: html </details> -Then, in the same file, we make ``USE_MYMATH`` control which square root -function is used: - -.. raw:: html - - <details><summary>TODO 12: Click to show/hide answer</summary> - -.. literalinclude:: Step3/tutorial.cxx - :caption: TODO 12 : tutorial.cxx - :name: tutorial.cxx-ifdef-const - :language: c++ - :start-after: // which square root function should we use? - :end-before: std::cout << "The square root of +Finally, we need to include ``cmath`` now that we are using ``std::sqrt``. .. raw:: html - </details> - -Since the source code now requires ``USE_MYMATH`` we can add it to -``TutorialConfig.h.in`` with the following line: - -.. raw:: html + <details><summary>TODO 11: Click to show/hide answer</summary> - <details><summary>TODO 13: Click to show/hide answer</summary> +.. code-block:: c++ + :caption: TODO 11 : MathFunctions/MathFunctions.cxx + :name: tutorial.cxx-include_cmath -.. literalinclude:: Step3/TutorialConfig.h.in - :caption: TODO 13 : TutorialConfig.h.in - :name: TutorialConfig.h.in-cmakedefine - :language: c++ - :lines: 4 + #include <cmath> .. raw:: html </details> -With these changes, our library is now completely optional to whoever is -building and using it. - -Bonus Question --------------- - -Why is it important that we configure ``TutorialConfig.h.in`` -after the option for ``USE_MYMATH``? What would happen if we inverted the two? - -Answer ------- +When ``USE_MYMATH`` is ``ON``, the compile definition ``USE_MYMATH`` will +be set. We can then use this compile definition to enable or disable +sections of our source code. With this strategy, we allow users to +toggle ``USE_MYMATH`` to manipulate what library is used in the build. -.. raw:: html - - <details><summary>Click to show/hide answer</summary> - -We configure after because ``TutorialConfig.h.in`` uses the value of -``USE_MYMATH``. If we configure the file before -calling :command:`option`, we won't be using the expected value of -``USE_MYMATH``. - -.. raw:: html - - </details> +With these changes, the ``mysqrt`` function is now completely optional to +whoever is building and using the ``MathFunctions`` library. diff --git a/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.cxx index 0145300..c0991b9 100644 --- a/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/Complete/MathFunctions/MathFunctions.cxx @@ -10,6 +10,7 @@ namespace mathfunctions { double sqrt(double x) { +// which square root function should we use? #ifdef USE_MYMATH return detail::mysqrt(x); #else diff --git a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst index 7befe1d..504e42f 100644 --- a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst +++ b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst @@ -10,49 +10,22 @@ To accomplish this we need to add :variable:`BUILD_SHARED_LIBS` to the top-level ``CMakeLists.txt``. We use the :command:`option` command as it allows users to optionally select if the value should be ``ON`` or ``OFF``. -Next we are going to refactor ``MathFunctions`` to become a real library that -encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling -code to do this logic. This will also mean that ``USE_MYMATH`` will not control -building ``MathFunctions``, but instead will control the behavior of this -library. - -The first step is to update the starting section of the top-level -``CMakeLists.txt`` to look like: - .. literalinclude:: Step11/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-option-BUILD_SHARED_LIBS :language: cmake - :end-before: # add the binary tree - -Now that we have made ``MathFunctions`` always be used, we will need to update -the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to -create a SqrtLibrary that will conditionally be built and installed when -``USE_MYMATH`` is enabled. Now, since this is a tutorial, we are going to -explicitly require that SqrtLibrary is built statically. + :start-after: set(CMAKE_RUNTIME_OUTPUT_DIRECTORY + :end-before: # configure a header file to pass the version number only -The end result is that ``MathFunctions/CMakeLists.txt`` should look like: +Next, we need to specify output directories for our static and shared +libraries. -.. literalinclude:: Step11/MathFunctions/CMakeLists.txt - :caption: MathFunctions/CMakeLists.txt - :name: MathFunctions/CMakeLists.txt-add_library-STATIC +.. literalinclude:: Step11/CMakeLists.txt + :caption: CMakeLists.txt + :name: CMakeLists.txt-cmake-output-directories :language: cmake - :lines: 1-36,42- - -Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and -``detail`` namespaces: - -.. literalinclude:: Step11/MathFunctions/mysqrt.cxx - :caption: MathFunctions/mysqrt.cxx - :name: MathFunctions/mysqrt.cxx-namespace - :language: c++ - -We also need to make some changes in ``tutorial.cxx``, so that it no longer -uses ``USE_MYMATH``: - -#. Always include ``MathFunctions.h`` -#. Always use ``mathfunctions::sqrt`` -#. Don't include ``cmath`` + :start-after: # we don't need to tinker with the path to run the executable + :end-before: # configure a header file to pass the version number only Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: diff --git a/Help/guide/tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step10/CMakeLists.txt index 5c661aa..2dd6db5 100644 --- a/Help/guide/tutorial/Step10/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/CMakeLists.txt @@ -16,22 +16,15 @@ target_compile_options(tutorial_compiler_flags INTERFACE "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" ) -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) - -# configure a header file to pass some of the CMake settings -# to the source code +# configure a header file to pass the version number only configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library -if(USE_MYMATH) - add_subdirectory(MathFunctions) - list(APPEND EXTRA_LIBS MathFunctions) -endif() +add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) +target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt index fa73321..6f6c430 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt @@ -1,32 +1,51 @@ -# first we add the executable that generates the table -add_executable(MakeTable MakeTable.cxx) - -# add the command to generate the source code -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h - COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h - DEPENDS MakeTable - ) - -# add the main library -add_library(MathFunctions - mysqrt.cxx - ${CMAKE_CURRENT_BINARY_DIR}/Table.h - ) +# add the library that runs +add_library(MathFunctions MathFunctions.cxx) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. -# state that we depend on our binary dir to find Table.h target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${CMAKE_CURRENT_BINARY_DIR} - ) + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + ) -# link our compiler flags interface library -target_link_libraries(MathFunctions tutorial_compiler_flags) +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) +if(USE_MYMATH) + + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") + + # first we add the executable that generates the table + add_executable(MakeTable MakeTable.cxx) + target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags) + + # add the command to generate the source code + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h + COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h + DEPENDS MakeTable + ) + + # library that just does sqrt + add_library(SqrtLibrary STATIC + mysqrt.cxx + ${CMAKE_CURRENT_BINARY_DIR}/Table.h + ) + + # state that we depend on our binary dir to find Table.h + target_include_directories(SqrtLibrary PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ) + + target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags) + target_link_libraries(MathFunctions PRIVATE SqrtLibrary) +endif() + +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # install libs set(installable_libs MathFunctions tutorial_compiler_flags) +if(TARGET SqrtLibrary) + list(APPEND installable_libs SqrtLibrary) +endif() install(TARGETS ${installable_libs} DESTINATION lib) # install include headers install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.cxx index 0145300..c0991b9 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.cxx @@ -10,6 +10,7 @@ namespace mathfunctions { double sqrt(double x) { +// which square root function should we use? #ifdef USE_MYMATH return detail::mysqrt(x); #else diff --git a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h index cd36bcc..1e916e1 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h @@ -1 +1,3 @@ -double mysqrt(double x); +namespace mathfunctions { +double sqrt(double x); +} diff --git a/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx index 7d80ee9..8153f18 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx @@ -5,6 +5,8 @@ // include the generated table #include "Table.h" +namespace mathfunctions { +namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -31,3 +33,5 @@ double mysqrt(double x) return result; } +} +} diff --git a/Help/guide/tutorial/Step10/TutorialConfig.h.in b/Help/guide/tutorial/Step10/TutorialConfig.h.in index e23f521..7e4d7fa 100644 --- a/Help/guide/tutorial/Step10/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step10/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step10/tutorial.cxx b/Help/guide/tutorial/Step10/tutorial.cxx index b3c6a4f..37a0333 100644 --- a/Help/guide/tutorial/Step10/tutorial.cxx +++ b/Help/guide/tutorial/Step10/tutorial.cxx @@ -1,15 +1,11 @@ // A simple program that computes the square root of a number -#include <cmath> #include <iostream> +#include <sstream> #include <string> +#include "MathFunctions.h" #include "TutorialConfig.h" -// should we include the MathFunctions header? -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - int main(int argc, char* argv[]) { if (argc < 2) { @@ -23,12 +19,7 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // which square root function should we use? -#ifdef USE_MYMATH - const double outputValue = mysqrt(inputValue); -#else - const double outputValue = sqrt(inputValue); -#endif + const double outputValue = mathfunctions::sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.cxx index 0145300..c0991b9 100644 --- a/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/Step11/MathFunctions/MathFunctions.cxx @@ -10,6 +10,7 @@ namespace mathfunctions { double sqrt(double x) { +// which square root function should we use? #ifdef USE_MYMATH return detail::mysqrt(x); #else diff --git a/Help/guide/tutorial/Step12/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step12/MathFunctions/MathFunctions.cxx index 0145300..c0991b9 100644 --- a/Help/guide/tutorial/Step12/MathFunctions/MathFunctions.cxx +++ b/Help/guide/tutorial/Step12/MathFunctions/MathFunctions.cxx @@ -10,6 +10,7 @@ namespace mathfunctions { double sqrt(double x) { +// which square root function should we use? #ifdef USE_MYMATH return detail::mysqrt(x); #else diff --git a/Help/guide/tutorial/Step2/CMakeLists.txt b/Help/guide/tutorial/Step2/CMakeLists.txt index 2b96128..0a06ed7 100644 --- a/Help/guide/tutorial/Step2/CMakeLists.txt +++ b/Help/guide/tutorial/Step2/CMakeLists.txt @@ -7,36 +7,20 @@ project(Tutorial VERSION 1.0) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) -# TODO 7: Create a variable USE_MYMATH using option and set default to ON - # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) -# TODO 8: Use list() and APPEND to create a list of optional libraries -# called EXTRA_LIBS and a list of optional include directories called -# EXTRA_INCLUDES. Add the MathFunctions library and source directory to -# the appropriate lists. -# -# Only call add_subdirectory and only add MathFunctions specific values -# to EXTRA_LIBS and EXTRA_INCLUDES if USE_MYMATH is true. - # TODO 2: Use add_subdirectory() to add MathFunctions to this project # add the executable add_executable(Tutorial tutorial.cxx) -# TODO 9: Use EXTRA_LIBS instead of the MathFunctions specific values -# in target_link_libraries. - # TODO 3: Use target_link_libraries to link the library to our executable # TODO 4: Add MathFunctions to Tutorial's target_include_directories() # Hint: ${PROJECT_SOURCE_DIR} is a path to the project source. AKA This folder! -# TODO 10: Use EXTRA_INCLUDES instead of the MathFunctions specific values -# in target_include_directories. - # add the binary tree to the search path for include files # so that we will find TutorialConfig.h target_include_directories(Tutorial PUBLIC diff --git a/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt index b7779b7..c468b0e 100644 --- a/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt @@ -1,2 +1,7 @@ # TODO 1: Add a library called MathFunctions # Hint: You will need the add_library command + +# TODO 7: Create a variable USE_MYMATH using option and set default to ON + +# TODO 8: If USE_MYMATH is ON, use target_compile_definitions to pass +# USE_MYMATH as a precompiled definition to our source files diff --git a/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..781d0ec --- /dev/null +++ b/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.cxx @@ -0,0 +1,15 @@ +#include "MathFunctions.h" + +// TODO 11: include cmath + +// TODO 10: Wrap the mysqrt include in a precompiled ifdef based on USE_MYMATH +#include "mysqrt.h" + +namespace mathfunctions { +double sqrt(double x) +{ + // TODO 9: If USE_MYMATH is defined, use detail::mysqrt. + // Otherwise, use std::sqrt. + return detail::mysqrt(x); +} +} diff --git a/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.h index cd36bcc..d5c2f22 100644 --- a/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step2/MathFunctions/MathFunctions.h @@ -1 +1,5 @@ -double mysqrt(double x); +#pragma once + +namespace mathfunctions { +double sqrt(double x); +} diff --git a/Help/guide/tutorial/Step2/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step2/MathFunctions/mysqrt.cxx index 1e4d97a..ba0ac64 100644 --- a/Help/guide/tutorial/Step2/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step2/MathFunctions/mysqrt.cxx @@ -1,5 +1,9 @@ +#include "mysqrt.h" + #include <iostream> +namespace mathfunctions { +namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -20,3 +24,5 @@ double mysqrt(double x) } return result; } +} +} diff --git a/Help/guide/tutorial/Step2/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step2/MathFunctions/mysqrt.h new file mode 100644 index 0000000..593d41e --- /dev/null +++ b/Help/guide/tutorial/Step2/MathFunctions/mysqrt.h @@ -0,0 +1,7 @@ +#pragma once + +namespace mathfunctions { +namespace detail { +double mysqrt(double x); +} +} diff --git a/Help/guide/tutorial/Step2/TutorialConfig.h.in b/Help/guide/tutorial/Step2/TutorialConfig.h.in index 6c09e1a..7e4d7fa 100644 --- a/Help/guide/tutorial/Step2/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step2/TutorialConfig.h.in @@ -1,5 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ - -// TODO 13: use cmakedefine to define USE_MYMATH diff --git a/Help/guide/tutorial/Step2/tutorial.cxx b/Help/guide/tutorial/Step2/tutorial.cxx index 87f5e0f..7a2a595 100644 --- a/Help/guide/tutorial/Step2/tutorial.cxx +++ b/Help/guide/tutorial/Step2/tutorial.cxx @@ -3,11 +3,8 @@ #include <iostream> #include <string> -#include "TutorialConfig.h" - -// TODO 11: Only include MathFunctions if USE_MYMATH is defined - // TODO 5: Include MathFunctions.h +#include "TutorialConfig.h" int main(int argc, char* argv[]) { @@ -22,9 +19,7 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // TODO 12: Use mysqrt if USE_MYMATH is defined and sqrt otherwise - - // TODO 6: Replace sqrt with mysqrt + // TODO 6: Replace sqrt with mathfunctions::sqrt // calculate square root const double outputValue = sqrt(inputValue); diff --git a/Help/guide/tutorial/Step3/CMakeLists.txt b/Help/guide/tutorial/Step3/CMakeLists.txt index 007770a..f051826 100644 --- a/Help/guide/tutorial/Step3/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/CMakeLists.txt @@ -7,9 +7,6 @@ project(Tutorial VERSION 1.0) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) - # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) @@ -17,16 +14,13 @@ configure_file(TutorialConfig.h.in TutorialConfig.h) # TODO 2: Remove EXTRA_INCLUDES list # add the MathFunctions library -if(USE_MYMATH) - add_subdirectory(MathFunctions) - list(APPEND EXTRA_LIBS MathFunctions) - list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions") -endif() +add_subdirectory(MathFunctions) +list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions") # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC MathFunctions) # TODO 3: Remove use of EXTRA_INCLUDES diff --git a/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt index 7bf05e0..90d6c24 100644 --- a/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt @@ -1,5 +1,11 @@ -add_library(MathFunctions mysqrt.cxx) +add_library(MathFunctions MathFunctions.cxx mysqrt.cxx) # TODO 1: State that anybody linking to MathFunctions needs to include the # current source directory, while MathFunctions itself doesn't. # Hint: Use target_include_directories with the INTERFACE keyword + +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) +if (USE_MYMATH) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") +endif() diff --git a/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..dc28b4b --- /dev/null +++ b/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.cxx @@ -0,0 +1,19 @@ +#include "MathFunctions.h" + +#include <cmath> + +#ifdef USE_MYMATH +# include "mysqrt.h" +#endif + +namespace mathfunctions { +double sqrt(double x) +{ +// which square root function should we use? +#ifdef USE_MYMATH + return detail::mysqrt(x); +#else + return std::sqrt(x); +#endif +} +} diff --git a/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.h index cd36bcc..d5c2f22 100644 --- a/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step3/MathFunctions/MathFunctions.h @@ -1 +1,5 @@ -double mysqrt(double x); +#pragma once + +namespace mathfunctions { +double sqrt(double x); +} diff --git a/Help/guide/tutorial/Step3/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step3/MathFunctions/mysqrt.cxx index abe767d..ba0ac64 100644 --- a/Help/guide/tutorial/Step3/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step3/MathFunctions/mysqrt.cxx @@ -1,7 +1,9 @@ -#include <iostream> +#include "mysqrt.h" -#include "MathFunctions.h" +#include <iostream> +namespace mathfunctions { +namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -22,3 +24,5 @@ double mysqrt(double x) } return result; } +} +} diff --git a/Help/guide/tutorial/Step3/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step3/MathFunctions/mysqrt.h new file mode 100644 index 0000000..593d41e --- /dev/null +++ b/Help/guide/tutorial/Step3/MathFunctions/mysqrt.h @@ -0,0 +1,7 @@ +#pragma once + +namespace mathfunctions { +namespace detail { +double mysqrt(double x); +} +} diff --git a/Help/guide/tutorial/Step3/TutorialConfig.h.in b/Help/guide/tutorial/Step3/TutorialConfig.h.in index e23f521..7e4d7fa 100644 --- a/Help/guide/tutorial/Step3/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step3/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step3/tutorial.cxx b/Help/guide/tutorial/Step3/tutorial.cxx index b3c6a4f..a3a2bdc 100644 --- a/Help/guide/tutorial/Step3/tutorial.cxx +++ b/Help/guide/tutorial/Step3/tutorial.cxx @@ -3,13 +3,9 @@ #include <iostream> #include <string> +#include "MathFunctions.h" #include "TutorialConfig.h" -// should we include the MathFunctions header? -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - int main(int argc, char* argv[]) { if (argc < 2) { @@ -23,12 +19,7 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // which square root function should we use? -#ifdef USE_MYMATH - const double outputValue = mysqrt(inputValue); -#else - const double outputValue = sqrt(inputValue); -#endif + const double outputValue = mathfunctions::sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/guide/tutorial/Step4/CMakeLists.txt b/Help/guide/tutorial/Step4/CMakeLists.txt index fa4aab2..dcda135 100644 --- a/Help/guide/tutorial/Step4/CMakeLists.txt +++ b/Help/guide/tutorial/Step4/CMakeLists.txt @@ -31,25 +31,19 @@ set(CMAKE_CXX_STANDARD_REQUIRED True) # build-tree # Hint: Use BUILD_INTERFACE -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) - # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library -if(USE_MYMATH) - add_subdirectory(MathFunctions) - list(APPEND EXTRA_LIBS MathFunctions) -endif() +add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) # TODO 2: Link to tutorial_compiler_flags -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC MathFunctions) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt index 5f7369c..cc71d86 100644 --- a/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt @@ -1,9 +1,15 @@ -add_library(MathFunctions mysqrt.cxx) +add_library(MathFunctions MathFunctions.cxx mysqrt.cxx) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - ) + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + ) + +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) +if (USE_MYMATH) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") +endif() # TODO 3: Link to tutorial_compiler_flags diff --git a/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..dc28b4b --- /dev/null +++ b/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.cxx @@ -0,0 +1,19 @@ +#include "MathFunctions.h" + +#include <cmath> + +#ifdef USE_MYMATH +# include "mysqrt.h" +#endif + +namespace mathfunctions { +double sqrt(double x) +{ +// which square root function should we use? +#ifdef USE_MYMATH + return detail::mysqrt(x); +#else + return std::sqrt(x); +#endif +} +} diff --git a/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.h index cd36bcc..d5c2f22 100644 --- a/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step4/MathFunctions/MathFunctions.h @@ -1 +1,5 @@ -double mysqrt(double x); +#pragma once + +namespace mathfunctions { +double sqrt(double x); +} diff --git a/Help/guide/tutorial/Step4/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step4/MathFunctions/mysqrt.cxx index abe767d..ba0ac64 100644 --- a/Help/guide/tutorial/Step4/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step4/MathFunctions/mysqrt.cxx @@ -1,7 +1,9 @@ -#include <iostream> +#include "mysqrt.h" -#include "MathFunctions.h" +#include <iostream> +namespace mathfunctions { +namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -22,3 +24,5 @@ double mysqrt(double x) } return result; } +} +} diff --git a/Help/guide/tutorial/Step4/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step4/MathFunctions/mysqrt.h new file mode 100644 index 0000000..593d41e --- /dev/null +++ b/Help/guide/tutorial/Step4/MathFunctions/mysqrt.h @@ -0,0 +1,7 @@ +#pragma once + +namespace mathfunctions { +namespace detail { +double mysqrt(double x); +} +} diff --git a/Help/guide/tutorial/Step4/TutorialConfig.h.in b/Help/guide/tutorial/Step4/TutorialConfig.h.in index e23f521..7e4d7fa 100644 --- a/Help/guide/tutorial/Step4/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step4/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step4/tutorial.cxx b/Help/guide/tutorial/Step4/tutorial.cxx index b3c6a4f..a3a2bdc 100644 --- a/Help/guide/tutorial/Step4/tutorial.cxx +++ b/Help/guide/tutorial/Step4/tutorial.cxx @@ -3,13 +3,9 @@ #include <iostream> #include <string> +#include "MathFunctions.h" #include "TutorialConfig.h" -// should we include the MathFunctions header? -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - int main(int argc, char* argv[]) { if (argc < 2) { @@ -23,12 +19,7 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // which square root function should we use? -#ifdef USE_MYMATH - const double outputValue = mysqrt(inputValue); -#else - const double outputValue = sqrt(inputValue); -#endif + const double outputValue = mathfunctions::sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/guide/tutorial/Step5/CMakeLists.txt b/Help/guide/tutorial/Step5/CMakeLists.txt index 279ddf9..ad814f6 100644 --- a/Help/guide/tutorial/Step5/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/CMakeLists.txt @@ -16,22 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" ) -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) - # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library -if(USE_MYMATH) - add_subdirectory(MathFunctions) - list(APPEND EXTRA_LIBS MathFunctions) -endif() +add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) + +target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt index 6cd88d7..000a786 100644 --- a/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt @@ -1,13 +1,19 @@ -add_library(MathFunctions mysqrt.cxx) +add_library(MathFunctions MathFunctions.cxx mysqrt.cxx) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - ) + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + ) + +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) +if (USE_MYMATH) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") +endif() # link our compiler flags interface library -target_link_libraries(MathFunctions tutorial_compiler_flags) +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # TODO 1: Create a variable called installable_libs that is a list of all # libraries we want to install (e.g. MathFunctions and tutorial_compiler_flags) diff --git a/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..dc28b4b --- /dev/null +++ b/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.cxx @@ -0,0 +1,19 @@ +#include "MathFunctions.h" + +#include <cmath> + +#ifdef USE_MYMATH +# include "mysqrt.h" +#endif + +namespace mathfunctions { +double sqrt(double x) +{ +// which square root function should we use? +#ifdef USE_MYMATH + return detail::mysqrt(x); +#else + return std::sqrt(x); +#endif +} +} diff --git a/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.h index cd36bcc..d5c2f22 100644 --- a/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step5/MathFunctions/MathFunctions.h @@ -1 +1,5 @@ -double mysqrt(double x); +#pragma once + +namespace mathfunctions { +double sqrt(double x); +} diff --git a/Help/guide/tutorial/Step5/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step5/MathFunctions/mysqrt.cxx index abe767d..ba0ac64 100644 --- a/Help/guide/tutorial/Step5/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step5/MathFunctions/mysqrt.cxx @@ -1,7 +1,9 @@ -#include <iostream> +#include "mysqrt.h" -#include "MathFunctions.h" +#include <iostream> +namespace mathfunctions { +namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -22,3 +24,5 @@ double mysqrt(double x) } return result; } +} +} diff --git a/Help/guide/tutorial/Step5/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step5/MathFunctions/mysqrt.h new file mode 100644 index 0000000..593d41e --- /dev/null +++ b/Help/guide/tutorial/Step5/MathFunctions/mysqrt.h @@ -0,0 +1,7 @@ +#pragma once + +namespace mathfunctions { +namespace detail { +double mysqrt(double x); +} +} diff --git a/Help/guide/tutorial/Step5/TutorialConfig.h.in b/Help/guide/tutorial/Step5/TutorialConfig.h.in index e23f521..7e4d7fa 100644 --- a/Help/guide/tutorial/Step5/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step5/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step5/tutorial.cxx b/Help/guide/tutorial/Step5/tutorial.cxx index b3c6a4f..a3a2bdc 100644 --- a/Help/guide/tutorial/Step5/tutorial.cxx +++ b/Help/guide/tutorial/Step5/tutorial.cxx @@ -3,13 +3,9 @@ #include <iostream> #include <string> +#include "MathFunctions.h" #include "TutorialConfig.h" -// should we include the MathFunctions header? -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - int main(int argc, char* argv[]) { if (argc < 2) { @@ -23,12 +19,7 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // which square root function should we use? -#ifdef USE_MYMATH - const double outputValue = mysqrt(inputValue); -#else - const double outputValue = sqrt(inputValue); -#endif + const double outputValue = mathfunctions::sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/guide/tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt index c11e307..a86d60a 100644 --- a/Help/guide/tutorial/Step6/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/CMakeLists.txt @@ -16,22 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" ) -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) - # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library -if(USE_MYMATH) - add_subdirectory(MathFunctions) - list(APPEND EXTRA_LIBS MathFunctions) -endif() +add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) + +target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt index b4724c4..623cb74 100644 --- a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt @@ -1,13 +1,19 @@ -add_library(MathFunctions mysqrt.cxx) +add_library(MathFunctions MathFunctions.cxx mysqrt.cxx) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - ) + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + ) + +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) +if (USE_MYMATH) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") +endif() # link our compiler flags interface library -target_link_libraries(MathFunctions tutorial_compiler_flags) +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # install libs set(installable_libs MathFunctions tutorial_compiler_flags) diff --git a/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..dc28b4b --- /dev/null +++ b/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.cxx @@ -0,0 +1,19 @@ +#include "MathFunctions.h" + +#include <cmath> + +#ifdef USE_MYMATH +# include "mysqrt.h" +#endif + +namespace mathfunctions { +double sqrt(double x) +{ +// which square root function should we use? +#ifdef USE_MYMATH + return detail::mysqrt(x); +#else + return std::sqrt(x); +#endif +} +} diff --git a/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.h index cd36bcc..d5c2f22 100644 --- a/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step6/MathFunctions/MathFunctions.h @@ -1 +1,5 @@ -double mysqrt(double x); +#pragma once + +namespace mathfunctions { +double sqrt(double x); +} diff --git a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx index abe767d..ba0ac64 100644 --- a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx @@ -1,7 +1,9 @@ -#include <iostream> +#include "mysqrt.h" -#include "MathFunctions.h" +#include <iostream> +namespace mathfunctions { +namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -22,3 +24,5 @@ double mysqrt(double x) } return result; } +} +} diff --git a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.h new file mode 100644 index 0000000..593d41e --- /dev/null +++ b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.h @@ -0,0 +1,7 @@ +#pragma once + +namespace mathfunctions { +namespace detail { +double mysqrt(double x); +} +} diff --git a/Help/guide/tutorial/Step6/TutorialConfig.h.in b/Help/guide/tutorial/Step6/TutorialConfig.h.in index e23f521..7e4d7fa 100644 --- a/Help/guide/tutorial/Step6/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step6/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step6/tutorial.cxx b/Help/guide/tutorial/Step6/tutorial.cxx index b3c6a4f..a3a2bdc 100644 --- a/Help/guide/tutorial/Step6/tutorial.cxx +++ b/Help/guide/tutorial/Step6/tutorial.cxx @@ -3,13 +3,9 @@ #include <iostream> #include <string> +#include "MathFunctions.h" #include "TutorialConfig.h" -// should we include the MathFunctions header? -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - int main(int argc, char* argv[]) { if (argc < 2) { @@ -23,12 +19,7 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // which square root function should we use? -#ifdef USE_MYMATH - const double outputValue = mysqrt(inputValue); -#else - const double outputValue = sqrt(inputValue); -#endif + const double outputValue = mathfunctions::sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/guide/tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt index d26a90c..97ec6aa 100644 --- a/Help/guide/tutorial/Step7/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/CMakeLists.txt @@ -16,22 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" ) -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) - # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library -if(USE_MYMATH) - add_subdirectory(MathFunctions) - list(APPEND EXTRA_LIBS MathFunctions) -endif() +add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) + +target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt index e5bdc4d..c0d1e72 100644 --- a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt @@ -1,33 +1,39 @@ -add_library(MathFunctions mysqrt.cxx) +add_library(MathFunctions MathFunctions.cxx mysqrt.cxx) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - ) + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + ) -# link our compiler flags interface library -target_link_libraries(MathFunctions tutorial_compiler_flags) +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) +if (USE_MYMATH) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") + + # TODO 1: Include CheckCXXSourceCompiles -# TODO 1: Include CheckCXXSourceCompiles + # TODO 2: Use check_cxx_source_compiles with simple C++ code to verify + # availability of: + # * std::log + # * std::exp + # Store the results in HAVE_LOG and HAVE_EXP respectively. -# TODO 2: Use check_cxx_source_compiles with simple C++ code to verify -# availability of: -# * std::log -# * std::exp -# Store the results in HAVE_LOG and HAVE_EXP respectively. + # Hint: Sample C++ code which uses log: + # #include <cmath> + # int main() { + # std::log(1.0); + # return 0; + # } -# Hint: Sample C++ code which uses log: -# #include <cmath> -# int main() { -# std::log(1.0); -# return 0; -# } + # TODO 3: Conditionally on HAVE_LOG and HAVE_EXP, add private compile + # definitions "HAVE_LOG" and "HAVE_EXP" to the MathFunctions target. -# TODO 3: Conditionally on HAVE_LOG and HAVE_EXP, add private compile -# definitions "HAVE_LOG" and "HAVE_EXP" to the MathFunctions target. + # Hint: Use target_compile_definitions() +endif() -#Hint: Use target_compile_definitions() +# link our compiler flags interface library +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # install libs set(installable_libs MathFunctions tutorial_compiler_flags) diff --git a/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..dc28b4b --- /dev/null +++ b/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.cxx @@ -0,0 +1,19 @@ +#include "MathFunctions.h" + +#include <cmath> + +#ifdef USE_MYMATH +# include "mysqrt.h" +#endif + +namespace mathfunctions { +double sqrt(double x) +{ +// which square root function should we use? +#ifdef USE_MYMATH + return detail::mysqrt(x); +#else + return std::sqrt(x); +#endif +} +} diff --git a/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.h index cd36bcc..d5c2f22 100644 --- a/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step7/MathFunctions/MathFunctions.h @@ -1 +1,5 @@ -double mysqrt(double x); +#pragma once + +namespace mathfunctions { +double sqrt(double x); +} diff --git a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx index 3d2492a..9963cff 100644 --- a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx @@ -1,8 +1,9 @@ -#include <iostream> +#include "mysqrt.h" -// TODO 4: include cmath -#include "MathFunctions.h" +#include <iostream> +namespace mathfunctions { +namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -32,3 +33,5 @@ double mysqrt(double x) return result; } +} +} diff --git a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.h new file mode 100644 index 0000000..593d41e --- /dev/null +++ b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.h @@ -0,0 +1,7 @@ +#pragma once + +namespace mathfunctions { +namespace detail { +double mysqrt(double x); +} +} diff --git a/Help/guide/tutorial/Step7/TutorialConfig.h.in b/Help/guide/tutorial/Step7/TutorialConfig.h.in index e23f521..7e4d7fa 100644 --- a/Help/guide/tutorial/Step7/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step7/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step7/tutorial.cxx b/Help/guide/tutorial/Step7/tutorial.cxx index b3c6a4f..a3a2bdc 100644 --- a/Help/guide/tutorial/Step7/tutorial.cxx +++ b/Help/guide/tutorial/Step7/tutorial.cxx @@ -3,13 +3,9 @@ #include <iostream> #include <string> +#include "MathFunctions.h" #include "TutorialConfig.h" -// should we include the MathFunctions header? -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - int main(int argc, char* argv[]) { if (argc < 2) { @@ -23,12 +19,7 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // which square root function should we use? -#ifdef USE_MYMATH - const double outputValue = mysqrt(inputValue); -#else - const double outputValue = sqrt(inputValue); -#endif + const double outputValue = mathfunctions::sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/guide/tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt index cb87281..97ec6aa 100644 --- a/Help/guide/tutorial/Step8/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/CMakeLists.txt @@ -16,23 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" ) - -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) - # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library -if(USE_MYMATH) - add_subdirectory(MathFunctions) - list(APPEND EXTRA_LIBS MathFunctions) -endif() +add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) + +target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt index f81b563..861014d 100644 --- a/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt @@ -1,36 +1,43 @@ -add_library(MathFunctions mysqrt.cxx) +add_library(MathFunctions MathFunctions.cxx mysqrt.cxx) + +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) +if (USE_MYMATH) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") + + # does this system provide the log and exp functions? + include(CheckCXXSourceCompiles) + check_cxx_source_compiles(" + #include <cmath> + int main() { + std::log(1.0); + return 0; + } + " HAVE_LOG) + check_cxx_source_compiles(" + #include <cmath> + int main() { + std::exp(1.0); + return 0; + } + " HAVE_EXP) + + # add compile definitions + if(HAVE_LOG AND HAVE_EXP) + target_compile_definitions(MathFunctions + PRIVATE "HAVE_LOG" "HAVE_EXP" + ) + endif() +endif() # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - ) + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + ) # link our compiler flags interface library -target_link_libraries(MathFunctions tutorial_compiler_flags) - -# does this system provide the log and exp functions? -include(CheckCXXSourceCompiles) -check_cxx_source_compiles(" - #include <cmath> - int main() { - std::log(1.0); - return 0; - } -" HAVE_LOG) -check_cxx_source_compiles(" - #include <cmath> - int main() { - std::exp(1.0); - return 0; - } -" HAVE_EXP) - -# add compile definitions -if(HAVE_LOG AND HAVE_EXP) - target_compile_definitions(MathFunctions - PRIVATE "HAVE_LOG" "HAVE_EXP") -endif() +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # install libs set(installable_libs MathFunctions tutorial_compiler_flags) diff --git a/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..dc28b4b --- /dev/null +++ b/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.cxx @@ -0,0 +1,19 @@ +#include "MathFunctions.h" + +#include <cmath> + +#ifdef USE_MYMATH +# include "mysqrt.h" +#endif + +namespace mathfunctions { +double sqrt(double x) +{ +// which square root function should we use? +#ifdef USE_MYMATH + return detail::mysqrt(x); +#else + return std::sqrt(x); +#endif +} +} diff --git a/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.h index cd36bcc..d5c2f22 100644 --- a/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step8/MathFunctions/MathFunctions.h @@ -1 +1,5 @@ -double mysqrt(double x); +#pragma once + +namespace mathfunctions { +double sqrt(double x); +} diff --git a/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx index 7eecd26..28ab042 100644 --- a/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx @@ -1,8 +1,10 @@ +#include "mysqrt.h" + #include <cmath> #include <iostream> -#include "MathFunctions.h" - +namespace mathfunctions { +namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -30,3 +32,5 @@ double mysqrt(double x) #endif return result; } +} +} diff --git a/Help/guide/tutorial/Step8/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.h new file mode 100644 index 0000000..593d41e --- /dev/null +++ b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.h @@ -0,0 +1,7 @@ +#pragma once + +namespace mathfunctions { +namespace detail { +double mysqrt(double x); +} +} diff --git a/Help/guide/tutorial/Step8/TutorialConfig.h.in b/Help/guide/tutorial/Step8/TutorialConfig.h.in index e23f521..7e4d7fa 100644 --- a/Help/guide/tutorial/Step8/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step8/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step8/tutorial.cxx b/Help/guide/tutorial/Step8/tutorial.cxx index b3c6a4f..a3a2bdc 100644 --- a/Help/guide/tutorial/Step8/tutorial.cxx +++ b/Help/guide/tutorial/Step8/tutorial.cxx @@ -3,13 +3,9 @@ #include <iostream> #include <string> +#include "MathFunctions.h" #include "TutorialConfig.h" -// should we include the MathFunctions header? -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - int main(int argc, char* argv[]) { if (argc < 2) { @@ -23,12 +19,7 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // which square root function should we use? -#ifdef USE_MYMATH - const double outputValue = mysqrt(inputValue); -#else - const double outputValue = sqrt(inputValue); -#endif + const double outputValue = mathfunctions::sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/guide/tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt index d26a90c..97ec6aa 100644 --- a/Help/guide/tutorial/Step9/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/CMakeLists.txt @@ -16,22 +16,17 @@ target_compile_options(tutorial_compiler_flags INTERFACE "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" ) -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) - # configure a header file to pass some of the CMake settings # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) # add the MathFunctions library -if(USE_MYMATH) - add_subdirectory(MathFunctions) - list(APPEND EXTRA_LIBS MathFunctions) -endif() +add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) + +target_link_libraries(Tutorial PUBLIC MathFunctions tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h diff --git a/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt index 8e04f97..05c8616 100644 --- a/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt @@ -1,34 +1,49 @@ -# first we add the executable that generates the table -add_executable(MakeTable MakeTable.cxx) - -# add the command to generate the source code -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h - COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h - DEPENDS MakeTable - ) - -# add the main library -add_library(MathFunctions - mysqrt.cxx - ${CMAKE_CURRENT_BINARY_DIR}/Table.h - ) +add_library(MathFunctions MathFunctions.cxx) # state that anybody linking to us needs to include the current source dir # to find MathFunctions.h, while we don't. -# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the -# TutorialConfig.h include is an implementation detail -# state that we depend on our binary dir to find Table.h target_include_directories(MathFunctions - INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} - PRIVATE ${CMAKE_CURRENT_BINARY_DIR} - ) + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + ) -# link our compiler flags interface library -target_link_libraries(MathFunctions tutorial_compiler_flags) +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) +if (USE_MYMATH) + target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") + + # first we add the executable that generates the table + add_executable(MakeTable MakeTable.cxx) + target_link_libraries(MakeTable PRIVATE tutorial_compiler_flags) + + # add the command to generate the source code + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h + COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h + DEPENDS MakeTable + ) + + # library that just does sqrt + add_library(SqrtLibrary STATIC + mysqrt.cxx + ${CMAKE_CURRENT_BINARY_DIR}/Table.h + ) + + # state that we depend on our binary dir to find Table.h + target_include_directories(SqrtLibrary PRIVATE + ${CMAKE_CURRENT_BINARY_DIR} + ) + + target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags) + target_link_libraries(MathFunctions PRIVATE SqrtLibrary) +endif() + +target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # install libs set(installable_libs MathFunctions tutorial_compiler_flags) +if(TARGET SqrtLibrary) + list(APPEND installable_libs SqrtLibrary) +endif() install(TARGETS ${installable_libs} DESTINATION lib) # install include headers install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..dc28b4b --- /dev/null +++ b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx @@ -0,0 +1,19 @@ +#include "MathFunctions.h" + +#include <cmath> + +#ifdef USE_MYMATH +# include "mysqrt.h" +#endif + +namespace mathfunctions { +double sqrt(double x) +{ +// which square root function should we use? +#ifdef USE_MYMATH + return detail::mysqrt(x); +#else + return std::sqrt(x); +#endif +} +} diff --git a/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.h index cd36bcc..d5c2f22 100644 --- a/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.h @@ -1 +1,5 @@ -double mysqrt(double x); +#pragma once + +namespace mathfunctions { +double sqrt(double x); +} diff --git a/Help/guide/tutorial/Step9/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.cxx index 7d80ee9..477d715 100644 --- a/Help/guide/tutorial/Step9/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.cxx @@ -1,10 +1,12 @@ -#include <iostream> +#include "mysqrt.h" -#include "MathFunctions.h" +#include <iostream> // include the generated table #include "Table.h" +namespace mathfunctions { +namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -31,3 +33,5 @@ double mysqrt(double x) return result; } +} +} diff --git a/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h new file mode 100644 index 0000000..593d41e --- /dev/null +++ b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h @@ -0,0 +1,7 @@ +#pragma once + +namespace mathfunctions { +namespace detail { +double mysqrt(double x); +} +} diff --git a/Help/guide/tutorial/Step9/TutorialConfig.h.in b/Help/guide/tutorial/Step9/TutorialConfig.h.in index e23f521..7e4d7fa 100644 --- a/Help/guide/tutorial/Step9/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step9/TutorialConfig.h.in @@ -1,4 +1,3 @@ // the configured options and settings for Tutorial #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@ -#cmakedefine USE_MYMATH diff --git a/Help/guide/tutorial/Step9/tutorial.cxx b/Help/guide/tutorial/Step9/tutorial.cxx index b3c6a4f..a3a2bdc 100644 --- a/Help/guide/tutorial/Step9/tutorial.cxx +++ b/Help/guide/tutorial/Step9/tutorial.cxx @@ -3,13 +3,9 @@ #include <iostream> #include <string> +#include "MathFunctions.h" #include "TutorialConfig.h" -// should we include the MathFunctions header? -#ifdef USE_MYMATH -# include "MathFunctions.h" -#endif - int main(int argc, char* argv[]) { if (argc < 2) { @@ -23,12 +19,7 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - // which square root function should we use? -#ifdef USE_MYMATH - const double outputValue = mysqrt(inputValue); -#else - const double outputValue = sqrt(inputValue); -#endif + const double outputValue = mathfunctions::sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index c3e87d7..8a92b4b 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -446,16 +446,20 @@ command. All paths are expected to be in cmake-style format. components from a path. See :ref:`Path Structure And Terminology` for the meaning of each path component. + .. versionchanged:: 3.27 + All operations now accept a list of paths as argument. When a list of paths + is specified, the operation will be applied to each path. + :: - $<PATH:GET_ROOT_NAME,path> - $<PATH:GET_ROOT_DIRECTORY,path> - $<PATH:GET_ROOT_PATH,path> - $<PATH:GET_FILENAME,path> - $<PATH:GET_EXTENSION[,LAST_ONLY],path> - $<PATH:GET_STEM[,LAST_ONLY],path> - $<PATH:GET_RELATIVE_PART,path> - $<PATH:GET_PARENT_PATH,path> + $<PATH:GET_ROOT_NAME,path...> + $<PATH:GET_ROOT_DIRECTORY,path...> + $<PATH:GET_ROOT_PATH,path...> + $<PATH:GET_FILENAME,path...> + $<PATH:GET_EXTENSION[,LAST_ONLY],path...> + $<PATH:GET_STEM[,LAST_ONLY],path...> + $<PATH:GET_RELATIVE_PART,path...> + $<PATH:GET_PARENT_PATH,path...> If a requested component is not present in the path, an empty string is returned. @@ -470,9 +474,14 @@ These expressions provide the generation-time capabilities equivalent to the options of the :command:`cmake_path` command. All paths are expected to be in cmake-style format. +.. versionchanged:: 3.27 + All operations now accept a list of paths as argument. When a list of paths + is specified, the operation will be applied to each path. + + .. _GenEx PATH-CMAKE_PATH: -.. genex:: $<PATH:CMAKE_PATH[,NORMALIZE],path> +.. genex:: $<PATH:CMAKE_PATH[,NORMALIZE],path...> .. versionadded:: 3.24 @@ -483,7 +492,7 @@ in cmake-style format. When the ``NORMALIZE`` option is specified, the path is :ref:`normalized <Normalization>` after the conversion. -.. genex:: $<PATH:APPEND,path,input,...> +.. genex:: $<PATH:APPEND,path...,input,...> .. versionadded:: 3.24 @@ -493,7 +502,7 @@ in cmake-style format. See :ref:`cmake_path(APPEND) <APPEND>` for more details. -.. genex:: $<PATH:REMOVE_FILENAME,path> +.. genex:: $<PATH:REMOVE_FILENAME,path...> .. versionadded:: 3.24 @@ -503,7 +512,7 @@ in cmake-style format. See :ref:`cmake_path(REMOVE_FILENAME) <REMOVE_FILENAME>` for more details. -.. genex:: $<PATH:REPLACE_FILENAME,path,input> +.. genex:: $<PATH:REPLACE_FILENAME,path...,input> .. versionadded:: 3.24 @@ -513,7 +522,7 @@ in cmake-style format. See :ref:`cmake_path(REPLACE_FILENAME) <REPLACE_FILENAME>` for more details. -.. genex:: $<PATH:REMOVE_EXTENSION[,LAST_ONLY],path> +.. genex:: $<PATH:REMOVE_EXTENSION[,LAST_ONLY],path...> .. versionadded:: 3.24 @@ -521,7 +530,7 @@ in cmake-style format. See :ref:`cmake_path(REMOVE_EXTENSION) <REMOVE_EXTENSION>` for more details. -.. genex:: $<PATH:REPLACE_EXTENSION[,LAST_ONLY],path,input> +.. genex:: $<PATH:REPLACE_EXTENSION[,LAST_ONLY],path...,input> .. versionadded:: 3.24 @@ -530,14 +539,14 @@ in cmake-style format. See :ref:`cmake_path(REPLACE_EXTENSION) <REPLACE_EXTENSION>` for more details. -.. genex:: $<PATH:NORMAL_PATH,path> +.. genex:: $<PATH:NORMAL_PATH,path...> .. versionadded:: 3.24 Returns ``path`` normalized according to the steps described in :ref:`Normalization`. -.. genex:: $<PATH:RELATIVE_PATH,path,base_directory> +.. genex:: $<PATH:RELATIVE_PATH,path...,base_directory> .. versionadded:: 3.24 @@ -547,7 +556,7 @@ in cmake-style format. See :ref:`cmake_path(RELATIVE_PATH) <cmake_path-RELATIVE_PATH>` for more details. -.. genex:: $<PATH:ABSOLUTE_PATH[,NORMALIZE],path,base_directory> +.. genex:: $<PATH:ABSOLUTE_PATH[,NORMALIZE],path...,base_directory> .. versionadded:: 3.24 diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 22e9eb2..e4c286d 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.27 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0144: find_package uses upper-case PACKAGENAME_ROOT variables. </policy/CMP0144> + Policies Introduced by CMake 3.26 ================================= diff --git a/Help/policy/CMP0144.rst b/Help/policy/CMP0144.rst new file mode 100644 index 0000000..3959d96 --- /dev/null +++ b/Help/policy/CMP0144.rst @@ -0,0 +1,26 @@ +CMP0144 +------- + +.. versionadded:: 3.27 + +:command:`find_package` uses upper-case ``<PACKAGENAME>_ROOT`` variables. + +In CMake 3.27 and above the :command:`find_package(<PackageName>)` command now +searches prefixes specified by the upper-case :variable:`<PACKAGENAME>_ROOT` +CMake variable and the :envvar:`<PACKAGENAME>_ROOT` environment variable +in addition to the case-preserved :variable:`<PackageName>_ROOT` and +:envvar:`<PackageName>_ROOT` variables used since policy :policy:`CMP0074`. +This policy provides compatibility with projects that have not been +updated to avoid using ``<PACKAGENAME>_ROOT`` variables for other purposes. + +The ``OLD`` behavior for this policy is to ignore ``<PACKAGENAME>_ROOT`` +variables if the original ``<PackageName>`` has lower-case characters. +The ``NEW`` behavior for this policy is to use ``<PACKAGENAME>_ROOT`` +variables. + +This policy was introduced in CMake version 3.27. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/PATH-genex-support-list.rst b/Help/release/dev/PATH-genex-support-list.rst new file mode 100644 index 0000000..ce87fdd --- /dev/null +++ b/Help/release/dev/PATH-genex-support-list.rst @@ -0,0 +1,5 @@ +PATH-genex-supports-list +------------------------ + +* The :genex:`$<PATH>` generator expression learned to process list of paths + for decomposition and transformation operations. diff --git a/Help/release/dev/find_package-PACKAGENAME_ROOT.rst b/Help/release/dev/find_package-PACKAGENAME_ROOT.rst new file mode 100644 index 0000000..0388271 --- /dev/null +++ b/Help/release/dev/find_package-PACKAGENAME_ROOT.rst @@ -0,0 +1,7 @@ +find_package-PACKAGENAME_ROOT +----------------------------- + +* The :command:`find_package` command now searches prefixes specified by + upper-case :variable:`<PACKAGENAME>_ROOT` CMake variables and upper-case + :envvar:`<PACKAGENAME>_ROOT` environment variables. + See policy :policy:`CMP0144`. diff --git a/Help/variable/PackageName_ROOT.rst b/Help/variable/PackageName_ROOT.rst index 6b17be3..8b728ba 100644 --- a/Help/variable/PackageName_ROOT.rst +++ b/Help/variable/PackageName_ROOT.rst @@ -14,3 +14,11 @@ This variable may hold a single prefix or a :ref:`semicolon-separated list <CMake Language Lists>` of multiple prefixes. See also the :envvar:`<PackageName>_ROOT` environment variable. + +.. variable:: <PACKAGENAME>_ROOT + + .. versionadded:: 3.27 + + Calls to :command:`find_package(<PackageName>)` will also search in + prefixes specified by the upper-case ``<PACKAGENAME>_ROOT`` CMake + variable. See policy :policy:`CMP0144`. diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 153563f..dd5f617 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -1536,7 +1536,9 @@ ExternalProject_Add_Step(${contentName}-populate copyfile if(CMAKE_GENERATOR_TOOLSET) list(APPEND subCMakeOpts "-T${CMAKE_GENERATOR_TOOLSET}") endif() - + if(CMAKE_GENERATOR_INSTANCE) + list(APPEND subCMakeOpts "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}") + endif() if(CMAKE_MAKE_PROGRAM) list(APPEND subCMakeOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}") endif() diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index ae1148d..4e8374c 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -120,12 +120,13 @@ macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library) unset(_OpenSSL_has_dependency_zlib) if(OPENSSL_USE_STATIC_LIBS) set(_OpenSSL_libs "${_OPENSSL_STATIC_LIBRARIES}") + set(_OpenSSL_ldflags_other "${_OPENSSL_STATIC_LDFLAGS_OTHER}") else() set(_OpenSSL_libs "${_OPENSSL_LIBRARIES}") + set(_OpenSSL_ldflags_other "${_OPENSSL_LDFLAGS_OTHER}") endif() if(_OpenSSL_libs) unset(_OpenSSL_has_dependency_dl) - unset(_OpenSSL_has_dependency_threads) foreach(_OPENSSL_DEP_LIB IN LISTS _OpenSSL_libs) if (_OPENSSL_DEP_LIB STREQUAL "ssl" OR _OPENSSL_DEP_LIB STREQUAL "crypto") # ignoring: these are the targets @@ -141,10 +142,22 @@ macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library) unset(_OPENSSL_DEP_LIB) else() set(_OpenSSL_has_dependency_dl TRUE) + endif() + if(_OpenSSL_ldflags_other) + unset(_OpenSSL_has_dependency_threads) + foreach(_OPENSSL_DEP_LDFLAG IN LISTS _OpenSSL_ldflags_other) + if (_OPENSSL_DEP_LDFLAG STREQUAL "-pthread") + set(_OpenSSL_has_dependency_threads TRUE) + find_package(Threads) + endif() + endforeach() + unset(_OPENSSL_DEP_LDFLAG) + else() set(_OpenSSL_has_dependency_threads TRUE) find_package(Threads) endif() unset(_OpenSSL_libs) + unset(_OpenSSL_ldflags_other) else() set(_OpenSSL_has_dependencies FALSE) endif() diff --git a/Modules/GenerateExportHeader.cmake b/Modules/GenerateExportHeader.cmake index 7461a3e..ea8616a 100644 --- a/Modules/GenerateExportHeader.cmake +++ b/Modules/GenerateExportHeader.cmake @@ -293,7 +293,7 @@ macro(_DO_SET_MACRO_VALUES TARGET_LIBRARY) set(DEFINE_IMPORT) set(DEFINE_NO_EXPORT) - if (COMPILER_HAS_DEPRECATED_ATTR) + if (COMPILER_HAS_DEPRECATED_ATTR AND NOT WIN32) set(DEFINE_DEPRECATED "__attribute__ ((__deprecated__))") elseif(COMPILER_HAS_DEPRECATED) set(DEFINE_DEPRECATED "__declspec(deprecated)") diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 53f1136..6fc286a 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 26) -set(CMake_VERSION_PATCH 20230223) +set(CMake_VERSION_PATCH 20230225) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index c1b82ab..5f1a2c5 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -975,35 +975,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } } - { - // Allocate a PACKAGE_ROOT_PATH for the current find_package call. - this->Makefile->FindPackageRootPathStack.emplace_back(); - std::vector<std::string>& rootPaths = - this->Makefile->FindPackageRootPathStack.back(); - - // Add root paths from <PackageName>_ROOT CMake and environment variables, - // subject to CMP0074. - switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0074)) { - case cmPolicies::WARN: - this->Makefile->MaybeWarnCMP0074(this->Name); - CM_FALLTHROUGH; - case cmPolicies::OLD: - // OLD behavior is to ignore the <pkg>_ROOT variables. - break; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0074)); - break; - case cmPolicies::NEW: { - // NEW behavior is to honor the <pkg>_ROOT variables. - std::string const rootVar = this->Name + "_ROOT"; - this->Makefile->GetDefExpandList(rootVar, rootPaths, false); - cmSystemTools::GetPath(rootPaths, rootVar.c_str()); - } break; - } - } + this->PushFindPackageRootPathStack(); this->SetModuleVariables(components, componentVarDefs); @@ -1129,8 +1101,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // Restore original state of "_FIND_" variables set in SetModuleVariables() this->RestoreFindDefinitions(); - // Pop the package stack - this->Makefile->FindPackageRootPathStack.pop_back(); + this->PopFindPackageRootPathStack(); if (!this->DebugBuffer.empty()) { this->DebugMessage(this->DebugBuffer); @@ -1834,6 +1805,99 @@ void cmFindPackageCommand::AppendSuccessInformation() } } +void cmFindPackageCommand::PushFindPackageRootPathStack() +{ + // Allocate a PACKAGE_ROOT_PATH for the current find_package call. + this->Makefile->FindPackageRootPathStack.emplace_back(); + std::vector<std::string>& rootPaths = + this->Makefile->FindPackageRootPathStack.back(); + + // Add root paths from <PackageName>_ROOT CMake and environment variables, + // subject to CMP0074. + std::string const rootVar = this->Name + "_ROOT"; + cmValue rootDef = this->Makefile->GetDefinition(rootVar); + if (rootDef && rootDef.IsEmpty()) { + rootDef = nullptr; + } + cm::optional<std::string> rootEnv = cmSystemTools::GetEnvVar(rootVar); + if (rootEnv && rootEnv->empty()) { + rootEnv = cm::nullopt; + } + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0074)) { + case cmPolicies::WARN: + this->Makefile->MaybeWarnCMP0074(rootVar, rootDef, rootEnv); + CM_FALLTHROUGH; + case cmPolicies::OLD: + // OLD behavior is to ignore the <PackageName>_ROOT variables. + return; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0074)); + return; + case cmPolicies::NEW: { + // NEW behavior is to honor the <PackageName>_ROOT variables. + } break; + } + + // Add root paths from <PACKAGENAME>_ROOT CMake and environment variables, + // if they are different than <PackageName>_ROOT, and subject to CMP0144. + std::string const rootVAR = cmSystemTools::UpperCase(rootVar); + cmValue rootDEF; + cm::optional<std::string> rootENV; + if (rootVAR != rootVar) { + rootDEF = this->Makefile->GetDefinition(rootVAR); + if (rootDEF && (rootDEF.IsEmpty() || rootDEF == rootDef)) { + rootDEF = nullptr; + } + rootENV = cmSystemTools::GetEnvVar(rootVAR); + if (rootENV && (rootENV->empty() || rootENV == rootEnv)) { + rootENV = cm::nullopt; + } + } + + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0144)) { + case cmPolicies::WARN: + this->Makefile->MaybeWarnCMP0144(rootVAR, rootDEF, rootENV); + CM_FALLTHROUGH; + case cmPolicies::OLD: + // OLD behavior is to ignore the <PACKAGENAME>_ROOT variables. + rootDEF = nullptr; + rootENV = cm::nullopt; + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0144)); + return; + case cmPolicies::NEW: { + // NEW behavior is to honor the <PACKAGENAME>_ROOT variables. + } break; + } + + if (rootDef) { + cmExpandList(*rootDef, rootPaths); + } + if (rootDEF) { + cmExpandList(*rootDEF, rootPaths); + } + if (rootEnv) { + std::vector<std::string> p = cmSystemTools::SplitEnvPath(*rootEnv); + std::move(p.begin(), p.end(), std::back_inserter(rootPaths)); + } + if (rootENV) { + std::vector<std::string> p = cmSystemTools::SplitEnvPath(*rootENV); + std::move(p.begin(), p.end(), std::back_inserter(rootPaths)); + } +} + +void cmFindPackageCommand::PopFindPackageRootPathStack() +{ + this->Makefile->FindPackageRootPathStack.pop_back(); +} + void cmFindPackageCommand::ComputePrefixes() { this->FillPrefixesPackageRedirect(); diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 28e00a1..18684c9 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -125,6 +125,9 @@ private: void StoreVersionFound(); void SetConfigDirCacheVariable(const std::string& value); + void PushFindPackageRootPathStack(); + void PopFindPackageRootPathStack(); + void ComputePrefixes(); void FillPrefixesPackageRedirect(); void FillPrefixesPackageRoot(); diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 5d761ac..5c7d217 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -688,6 +688,14 @@ static const struct PathNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* content, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { + static auto processList = + [](std::string const& arg, + std::function<void(std::string&)> transform) -> std::string { + auto list = cmExpandedList(arg); + std::for_each(list.begin(), list.end(), std::move(transform)); + return cmJoin(list, ";"); + }; + static std::unordered_map< cm::string_view, std::function<std::string(cmGeneratorExpressionContext*, @@ -698,38 +706,49 @@ static const struct PathNode : public cmGeneratorExpressionNode [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "GET_ROOT_NAME"_s, args) && - !args.front().empty() - ? cmCMakePath{ args.front() }.GetRootName().String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "GET_ROOT_NAME"_s, args) && + !args.front().empty()) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetRootName().String(); + }); + } + return std::string{}; } }, { "GET_ROOT_DIRECTORY"_s, [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "GET_ROOT_DIRECTORY"_s, - args) && - !args.front().empty() - ? cmCMakePath{ args.front() }.GetRootDirectory().String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "GET_ROOT_DIRECTORY"_s, args) && + !args.front().empty()) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetRootDirectory().String(); + }); + } + return std::string{}; } }, { "GET_ROOT_PATH"_s, [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "GET_ROOT_PATH"_s, args) && - !args.front().empty() - ? cmCMakePath{ args.front() }.GetRootPath().String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "GET_ROOT_PATH"_s, args) && + !args.front().empty()) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetRootPath().String(); + }); + } + return std::string{}; } }, { "GET_FILENAME"_s, [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "GET_FILENAME"_s, args) && - !args.front().empty() - ? cmCMakePath{ args.front() }.GetFileName().String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "GET_FILENAME"_s, args) && + !args.front().empty()) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetFileName().String(); + }); + } + return std::string{}; } }, { "GET_EXTENSION"_s, [](cmGeneratorExpressionContext* ctx, @@ -746,9 +765,14 @@ static const struct PathNode : public cmGeneratorExpressionNode if (args.front().empty()) { return std::string{}; } - return lastOnly - ? cmCMakePath{ args.front() }.GetExtension().String() - : cmCMakePath{ args.front() }.GetWideExtension().String(); + if (lastOnly) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetExtension().String(); + }); + } + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetWideExtension().String(); + }); } return std::string{}; } }, @@ -766,9 +790,14 @@ static const struct PathNode : public cmGeneratorExpressionNode if (args.front().empty()) { return std::string{}; } - return lastOnly - ? cmCMakePath{ args.front() }.GetStem().String() - : cmCMakePath{ args.front() }.GetNarrowStem().String(); + if (lastOnly) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetStem().String(); + }); + } + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetNarrowStem().String(); + }); } return std::string{}; } }, @@ -776,19 +805,24 @@ static const struct PathNode : public cmGeneratorExpressionNode [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "GET_RELATIVE_PART"_s, - args) && - !args.front().empty() - ? cmCMakePath{ args.front() }.GetRelativePath().String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "GET_RELATIVE_PART"_s, args) && + !args.front().empty()) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetRelativePath().String(); + }); + } + return std::string{}; } }, { "GET_PARENT_PATH"_s, [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "GET_PARENT_PATH"_s, args) - ? cmCMakePath{ args.front() }.GetParentPath().String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "GET_PARENT_PATH"_s, args)) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.GetParentPath().String(); + }); + } + return std::string{}; } }, { "HAS_ROOT_NAME"_s, [](cmGeneratorExpressionContext* ctx, @@ -904,10 +938,12 @@ static const struct PathNode : public cmGeneratorExpressionNode normalize ? "CMAKE_PATH,NORMALIZE"_s : "CMAKE_PATH"_s, args.size(), 1)) { - auto path = - cmCMakePath{ args.front(), cmCMakePath::auto_format }; - return normalize ? path.Normal().GenericString() - : path.GenericString(); + return processList( + args.front(), [normalize](std::string& value) { + auto path = cmCMakePath{ value, cmCMakePath::auto_format }; + value = normalize ? path.Normal().GenericString() + : path.GenericString(); + }); } return std::string{}; } }, @@ -917,11 +953,16 @@ static const struct PathNode : public cmGeneratorExpressionNode Arguments& args) -> std::string { if (CheckPathParametersEx(ctx, cnt, "APPEND"_s, args.size(), 1, false)) { - cmCMakePath path; - for (const auto& p : args) { - path /= p; - } - return path.String(); + auto const& list = args.front(); + args.advance(1); + + return processList(list, [&args](std::string& value) { + cmCMakePath path{ value }; + for (const auto& p : args) { + path /= p; + } + value = path.String(); + }); } return std::string{}; } }, @@ -929,20 +970,26 @@ static const struct PathNode : public cmGeneratorExpressionNode [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "REMOVE_FILENAME"_s, args) && - !args.front().empty() - ? cmCMakePath{ args.front() }.RemoveFileName().String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "REMOVE_FILENAME"_s, args) && + !args.front().empty()) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.RemoveFileName().String(); + }); + } + return std::string{}; } }, { "REPLACE_FILENAME"_s, [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "REPLACE_FILENAME"_s, args, 2) - ? cmCMakePath{ args[0] } - .ReplaceFileName(cmCMakePath{ args[1] }) - .String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "REPLACE_FILENAME"_s, args, 2)) { + return processList(args.front(), [&args](std::string& value) { + value = cmCMakePath{ value } + .ReplaceFileName(cmCMakePath{ args[1] }) + .String(); + }); + } + return std::string{}; } }, { "REMOVE_EXTENSION"_s, [](cmGeneratorExpressionContext* ctx, @@ -959,9 +1006,14 @@ static const struct PathNode : public cmGeneratorExpressionNode if (args.front().empty()) { return std::string{}; } - return lastOnly - ? cmCMakePath{ args.front() }.RemoveExtension().String() - : cmCMakePath{ args.front() }.RemoveWideExtension().String(); + if (lastOnly) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.RemoveExtension().String(); + }); + } + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.RemoveWideExtension().String(); + }); } return std::string{}; } }, @@ -979,13 +1031,17 @@ static const struct PathNode : public cmGeneratorExpressionNode : "REPLACE_EXTENSION"_s, args.size(), 2)) { if (lastOnly) { - return cmCMakePath{ args[0] } - .ReplaceExtension(cmCMakePath{ args[1] }) - .String(); + return processList(args.front(), [&args](std::string& value) { + value = cmCMakePath{ value } + .ReplaceExtension(cmCMakePath{ args[1] }) + .String(); + }); } - return cmCMakePath{ args[0] } - .ReplaceWideExtension(cmCMakePath{ args[1] }) - .String(); + return processList(args.front(), [&args](std::string& value) { + value = cmCMakePath{ value } + .ReplaceWideExtension(cmCMakePath{ args[1] }) + .String(); + }); } return std::string{}; } }, @@ -993,18 +1049,24 @@ static const struct PathNode : public cmGeneratorExpressionNode [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "NORMAL_PATH"_s, args) && - !args.front().empty() - ? cmCMakePath{ args.front() }.Normal().String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "NORMAL_PATH"_s, args) && + !args.front().empty()) { + return processList(args.front(), [](std::string& value) { + value = cmCMakePath{ value }.Normal().String(); + }); + } + return std::string{}; } }, { "RELATIVE_PATH"_s, [](cmGeneratorExpressionContext* ctx, const GeneratorExpressionContent* cnt, Arguments& args) -> std::string { - return CheckPathParameters(ctx, cnt, "RELATIVE_PATH"_s, args, 2) - ? cmCMakePath{ args[0] }.Relative(args[1]).String() - : std::string{}; + if (CheckPathParameters(ctx, cnt, "RELATIVE_PATH"_s, args, 2)) { + return processList(args.front(), [&args](std::string& value) { + value = cmCMakePath{ value }.Relative(args[1]).String(); + }); + } + return std::string{}; } }, { "ABSOLUTE_PATH"_s, [](cmGeneratorExpressionContext* ctx, @@ -1018,8 +1080,11 @@ static const struct PathNode : public cmGeneratorExpressionNode normalize ? "ABSOLUTE_PATH,NORMALIZE"_s : "ABSOLUTE_PATH"_s, args.size(), 2)) { - auto path = cmCMakePath{ args[0] }.Absolute(args[1]); - return normalize ? path.Normal().String() : path.String(); + return processList( + args.front(), [&args, normalize](std::string& value) { + auto path = cmCMakePath{ value }.Absolute(args[1]); + value = normalize ? path.Normal().String() : path.String(); + }); } return std::string{}; } } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index d963a5a..2fc2974 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -208,32 +208,47 @@ bool cmMakefile::CheckCMP0037(std::string const& targetName, return true; } -void cmMakefile::MaybeWarnCMP0074(std::string const& pkg) +void cmMakefile::MaybeWarnCMP0074(std::string const& rootVar, cmValue rootDef, + cm::optional<std::string> const& rootEnv) { - // Warn if a <pkg>_ROOT variable we may use is set. - std::string const varName = pkg + "_ROOT"; - cmValue var = this->GetDefinition(varName); - std::string env; - cmSystemTools::GetEnv(varName, env); - - bool const haveVar = cmNonempty(var); - bool const haveEnv = !env.empty(); - if ((haveVar || haveEnv) && this->WarnedCMP0074.insert(varName).second) { + // Warn if a <PackageName>_ROOT variable we may use is set. + if ((rootDef || rootEnv) && this->WarnedCMP0074.insert(rootVar).second) { std::ostringstream w; w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0074) << "\n"; - if (haveVar) { - w << "CMake variable " << varName << " is set to:\n" - << " " << *var << "\n"; + if (rootDef) { + w << "CMake variable " << rootVar << " is set to:\n" + << " " << *rootDef << "\n"; } - if (haveEnv) { - w << "Environment variable " << varName << " is set to:\n" - << " " << env << "\n"; + if (rootEnv) { + w << "Environment variable " << rootVar << " is set to:\n" + << " " << *rootEnv << "\n"; } w << "For compatibility, CMake is ignoring the variable."; this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } } +void cmMakefile::MaybeWarnCMP0144(std::string const& rootVAR, cmValue rootDEF, + cm::optional<std::string> const& rootENV) +{ + // Warn if a <PACKAGENAME>_ROOT variable we may use is set. + if ((rootDEF || rootENV) && this->WarnedCMP0144.insert(rootVAR).second) { + std::ostringstream w; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0144) << "\n"; + if (rootDEF) { + w << "CMake variable " << rootVAR << " is set to:\n" + << " " << *rootDEF << "\n"; + } + if (rootENV) { + w << "Environment variable " << rootVAR << " is set to:\n" + << " " << *rootENV << "\n"; + } + w << "For compatibility, find_package is ignoring the variable, but " + "code in a .cmake module might still use it."; + this->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); + } +} + cmBTStringRange cmMakefile::GetIncludeDirectoriesEntries() const { return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries(); diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 7b19c97..3cf6e61 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -1011,7 +1011,10 @@ public: bool GetDebugFindPkgMode() const; - void MaybeWarnCMP0074(std::string const& pkg); + void MaybeWarnCMP0074(std::string const& rootVar, cmValue rootDef, + cm::optional<std::string> const& rootEnv); + void MaybeWarnCMP0144(std::string const& rootVAR, cmValue rootDEF, + cm::optional<std::string> const& rootENV); void MaybeWarnUninitialized(std::string const& variable, const char* sourceFilename) const; bool IsProjectFile(const char* filename) const; @@ -1189,6 +1192,7 @@ private: bool CheckSystemVars; bool CheckCMP0000; std::set<std::string> WarnedCMP0074; + std::set<std::string> WarnedCMP0144; bool IsSourceFileTryCompile; mutable bool SuppressSideEffects; ImportedTargetScope CurrentImportedTargetScope = ImportedTargetScope::Local; diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 568eca3..1eca586 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -434,7 +434,10 @@ class cmMakefile; 3, 25, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0143, \ "Global property USE_FOLDERS treated as ON by default", 3, 26, 0, \ - cmPolicies::WARN) + cmPolicies::WARN) \ + SELECT(POLICY, CMP0144, \ + "find_package uses upper-case <PACKAGENAME>_ROOT variables.", 3, 27, \ + 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 3d61270..1fb0079 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1648,6 +1648,32 @@ std::string cmSystemTools::RelativeIfUnder(std::string const& top, return out; } +cm::optional<std::string> cmSystemTools::GetEnvVar(std::string const& var) +{ + cm::optional<std::string> result; + { + std::string value; + if (cmSystemTools::GetEnv(var, value)) { + result = std::move(value); + } + } + return result; +} + +std::vector<std::string> cmSystemTools::SplitEnvPath(std::string const& value) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + static cm::string_view sep = ";"_s; +#else + static cm::string_view sep = ":"_s; +#endif + std::vector<std::string> paths = cmTokenize(value, sep); + for (std::string& p : paths) { + SystemTools::ConvertToUnixSlashes(p); + } + return paths; +} + #ifndef CMAKE_BOOTSTRAP bool cmSystemTools::UnsetEnv(const char* value) { diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 09f2bf0..7d55d4b 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -399,6 +399,9 @@ public: static std::string RelativeIfUnder(std::string const& top, std::string const& in); + static cm::optional<std::string> GetEnvVar(std::string const& var); + static std::vector<std::string> SplitEnvPath(std::string const& value); + #ifndef CMAKE_BOOTSTRAP /** Remove an environment variable */ static bool UnsetEnv(const char* value); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index d57b78b..a2a9e09 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -2329,6 +2329,9 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg, cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL") == 0 || cmSystemTools::Strucmp(arg->c_str(), "-INCREMENTAL") == 0) { this->Incremental = true; + } else if (cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL:NO") == 0 || + cmSystemTools::Strucmp(arg->c_str(), "-INCREMENTAL:NO") == 0) { + this->Incremental = false; } else if (cmSystemTools::Strucmp(arg->c_str(), "/MANIFEST:NO") == 0 || cmSystemTools::Strucmp(arg->c_str(), "-MANIFEST:NO") == 0) { this->LinkGeneratesManifest = false; @@ -2353,17 +2356,11 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg, // pass it to the link command. this->ManifestFileRC = intDir + "/manifest.rc"; this->ManifestFileRes = intDir + "/manifest.res"; - } else if (this->UserManifests.empty()) { - // Prior to support for user-specified manifests CMake placed the - // linker-generated manifest next to the binary (as if it were not to be - // embedded) when not linking incrementally. Preserve this behavior. - this->ManifestFile = this->TargetFile + ".manifest"; - this->LinkerManifestFile = this->ManifestFile; - } - if (this->LinkGeneratesManifest) { - this->LinkCommand.emplace_back("/MANIFEST"); - this->LinkCommand.push_back("/MANIFESTFILE:" + this->LinkerManifestFile); + if (this->LinkGeneratesManifest) { + this->LinkCommand.emplace_back("/MANIFEST"); + this->LinkCommand.push_back("/MANIFESTFILE:" + this->LinkerManifestFile); + } } return true; @@ -2497,20 +2494,23 @@ int cmVSLink::LinkIncremental() int cmVSLink::LinkNonIncremental() { - // Run the link command (possibly generates intermediate manifest). - if (!RunCommand("LINK", this->LinkCommand, this->Verbose, FORMAT_DECIMAL)) { - return -1; - } + // Sort out any manifests. + if (this->LinkGeneratesManifest || !this->UserManifests.empty()) { + std::string opt = + std::string("/MANIFEST:EMBED,ID=") + (this->Type == 1 ? '1' : '2'); + this->LinkCommand.emplace_back(opt); - // If we have no manifest files we are done. - if (!this->LinkGeneratesManifest && this->UserManifests.empty()) { - return 0; + for (auto const& m : this->UserManifests) { + opt = "/MANIFESTINPUT:" + m; + this->LinkCommand.emplace_back(opt); + } } - // Run the manifest tool to embed the final manifest in the binary. - std::string mtOut = - "/outputresource:" + this->TargetFile + (this->Type == 1 ? ";#1" : ";#2"); - return this->RunMT(mtOut, false); + // Run the link command. + if (!RunCommand("LINK", this->LinkCommand, this->Verbose, FORMAT_DECIMAL)) { + return -1; + } + return 0; } int cmVSLink::RunMT(std::string const& out, bool notify) diff --git a/Tests/MSManifest/Subdir/CMakeLists.txt b/Tests/MSManifest/Subdir/CMakeLists.txt index 3b4fccc..68c66fe 100644 --- a/Tests/MSManifest/Subdir/CMakeLists.txt +++ b/Tests/MSManifest/Subdir/CMakeLists.txt @@ -5,6 +5,11 @@ if(MSVC AND NOT MSVC_VERSION LESS 1400) add_test(NAME MSManifest.Single COMMAND ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSManifest> -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) + add_executable(MSManifestNonIncremental main.c ${CMAKE_CURRENT_BINARY_DIR}/test.manifest) + set_property(TARGET MSManifestNonIncremental PROPERTY LINK_FLAGS "/INCREMENTAL:NO") + add_test(NAME MSManifest.Single.NonIncremental COMMAND + ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSManifestNonIncremental> + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) add_executable(MSManifestNone main.c) set_property(TARGET MSManifestNone PROPERTY LINK_FLAGS "/MANIFEST:NO") elseif(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "Clang") diff --git a/Tests/MSManifest/Subdir2/CMakeLists.txt b/Tests/MSManifest/Subdir2/CMakeLists.txt index 0d960ad..bbc70dc 100644 --- a/Tests/MSManifest/Subdir2/CMakeLists.txt +++ b/Tests/MSManifest/Subdir2/CMakeLists.txt @@ -10,4 +10,14 @@ if((MSVC AND NOT MSVC_VERSION LESS 1400) OR (WIN32 AND CMAKE_C_COMPILER_ID MATCH add_test(NAME MSManifest.Multiple COMMAND ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSMultipleManifest> -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) + if(MSVC AND NOT MSVC_VERSION LESS 1400) + add_executable(MSMultipleManifestNonIncremental main.c + ${CMAKE_CURRENT_BINARY_DIR}/test_manifest1.manifest + ${CMAKE_CURRENT_BINARY_DIR}/test_manifest2.manifest + ${CMAKE_CURRENT_BINARY_DIR}/test_manifest3.manifest) + set_property(TARGET MSMultipleManifestNonIncremental PROPERTY LINK_FLAGS "/INCREMENTAL:NO") + add_test(NAME MSManifest.Multiple.NonIncremental COMMAND + ${CMAKE_COMMAND} -Dexe=$<TARGET_FILE:MSMultipleManifestNonIncremental> + -P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake) + endif() endif() diff --git a/Tests/RunCMake/GenEx-PATH/ABSOLUTE_PATH.cmake.in b/Tests/RunCMake/GenEx-PATH/ABSOLUTE_PATH.cmake.in index cc5ff54..d1cb61b 100644 --- a/Tests/RunCMake/GenEx-PATH/ABSOLUTE_PATH.cmake.in +++ b/Tests/RunCMake/GenEx-PATH/ABSOLUTE_PATH.cmake.in @@ -31,4 +31,28 @@ if (NOT output STREQUAL reference) endif() +###################################### +## tests with list of paths +###################################### +unset (reference) +foreach(item IN ITEMS "../../a/d" "/a/d/../e") + cmake_path(ABSOLUTE_PATH item BASE_DIRECTORY "/x/y/a/f") + list(APPEND reference "${item}") +endforeach() +set(output "$<PATH:ABSOLUTE_PATH,../../a/d;/a/d/../e,/x/y/a/f>") +if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") +endif() + +unset (reference) +foreach(item IN ITEMS "../../a/d" "/a/d/../e") + cmake_path(ABSOLUTE_PATH item BASE_DIRECTORY "/x/y/a/f" NORMALIZE) + list(APPEND reference "${item}") +endforeach() +set(output "$<PATH:ABSOLUTE_PATH,NORMALIZE,../../a/d;/a/d/../e,/x/y/a/f>") +if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") +endif() + + check_errors("PATH:ABSOLUTE_PATH" ${errors}) diff --git a/Tests/RunCMake/GenEx-PATH/APPEND.cmake.in b/Tests/RunCMake/GenEx-PATH/APPEND.cmake.in index ab967a2..1955480 100644 --- a/Tests/RunCMake/GenEx-PATH/APPEND.cmake.in +++ b/Tests/RunCMake/GenEx-PATH/APPEND.cmake.in @@ -65,4 +65,39 @@ if (WIN32) endif() endif() + +###################################### +## tests with list of paths +###################################### +unset(reference) +foreach(item IN ITEMS "/a/b" "/x/y") + cmake_path (APPEND result "${item}" "c") + list(APPEND reference "${result}") +endforeach() +set(output "$<PATH:APPEND,/a/b;/x/y,c>") +if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") +endif() + +unset(reference) +foreach(item IN ITEMS "a" "c") + cmake_path (APPEND item "") + list(APPEND reference "${item}") +endforeach() +set(output "$<PATH:APPEND,a;c,>") +if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") +endif() + +unset(reference) +foreach(item IN ITEMS "a/" "c/") + cmake_path (APPEND item "/b") + list(APPEND reference "${item}") +endforeach() +set(output "$<PATH:APPEND,a/;c/,/b>") +if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") +endif() + + check_errors ("PATH:APPEND" ${errors}) diff --git a/Tests/RunCMake/GenEx-PATH/CMAKE_PATH.cmake.in b/Tests/RunCMake/GenEx-PATH/CMAKE_PATH.cmake.in index 41205fa..29ebf16 100644 --- a/Tests/RunCMake/GenEx-PATH/CMAKE_PATH.cmake.in +++ b/Tests/RunCMake/GenEx-PATH/CMAKE_PATH.cmake.in @@ -50,4 +50,46 @@ if (WIN32) endif() +###################################### +## tests with list of paths +###################################### +set(reference "/x/y/z/../../a/d;/x/y/z/../../b/e") +set(output "$<PATH:CMAKE_PATH,/x/y/z/../../a/d;/x/y/z/../../b/e>") +if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") +endif() + +unset(reference) +foreach(path IN ITEMS "/x/y/z/../../a/d" "/x/y/z/../../b/e") + cmake_path(SET result NORMALIZE "${path}") + list(APPEND reference "${result}") +endforeach() +set(output "$<PATH:CMAKE_PATH,NORMALIZE,/x/y/z/../../a/d;/x/y/z/../../b/e>") +if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") +endif() + +if (WIN32) + unset(reference) + foreach(path IN ITEMS "/x\\y/z\\..\\../a/d" "/x\\y/z\\..\\../b/e") + cmake_path(SET result "${path}") + list(APPEND reference "${result}") + endforeach() + set(output "$<PATH:CMAKE_PATH,/x\y/z\..\../a/d;/x\y/z\..\../b/e>") + if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") + endif() + + unset(reference) + foreach(path IN ITEMS "/x\\y/z\\..\\../a/d" "/x\\y/z\\..\\../b/e") + cmake_path(SET result NORMALIZE "${path}") + list(APPEND reference "${result}") + endforeach() + set(output "$<PATH:CMAKE_PATH,NORMALIZE,/x\y/z\..\../a/d;/x\y/z\..\../b/e>") + if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") + endif() +endif() + + check_errors("PATH:CMAKE_PATH" ${errors}) diff --git a/Tests/RunCMake/GenEx-PATH/CMakeLists.txt b/Tests/RunCMake/GenEx-PATH/CMakeLists.txt index f9748e9..5161b99 100644 --- a/Tests/RunCMake/GenEx-PATH/CMakeLists.txt +++ b/Tests/RunCMake/GenEx-PATH/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.18...3.24) +cmake_minimum_required(VERSION 3.18...3.25) project(${RunCMake_TEST} NONE) diff --git a/Tests/RunCMake/GenEx-PATH/GET_ITEM.cmake.in b/Tests/RunCMake/GenEx-PATH/GET_ITEM.cmake.in index b58998c..e2acde4 100644 --- a/Tests/RunCMake/GenEx-PATH/GET_ITEM.cmake.in +++ b/Tests/RunCMake/GenEx-PATH/GET_ITEM.cmake.in @@ -1,3 +1,4 @@ +cmake_policy(SET CMP0140 NEW) include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") unset (errors) @@ -308,4 +309,126 @@ if (NOT output STREQUAL reference) endif() +###################################### +## third, tests with list of paths +###################################### +if (WIN32) + set (paths "C:/aa/bb/cc.ext1.ext2" "D:/xx/yy/zz.ext3.ext4") +else() + set (paths "/aa/bb/cc.ext1.ext2" "/xx/yy/zz.ext3.ext4") +endif() + +function (compute_reference action) + unset(reference) + foreach (path IN LISTS paths) + cmake_path(GET path ${ARGV} result) + list(APPEND reference "${result}") + endforeach() + if (reference STREQUAL "") + # define the list as 2 empty elements + set(reference ";") + endif() + + return(PROPAGATE reference) +endfunction() + +compute_reference(ROOT_NAME) +if (WIN32) + set(output "$<PATH:GET_ROOT_NAME,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_ROOT_NAME,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "ROOT_NAME returns bad data: ${output}") +endif() + +compute_reference(ROOT_DIRECTORY) +if (WIN32) + set(output "$<PATH:GET_ROOT_DIRECTORY,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_ROOT_DIRECTORY,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "ROOT_DIRECTORY returns bad data: ${output}") +endif() + +compute_reference(ROOT_PATH) +if (WIN32) + set(output "$<PATH:GET_ROOT_PATH,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_ROOT_PATH,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "ROOT_PATH returns bad data: ${output}") +endif() + +compute_reference(FILENAME) +if (WIN32) + set(output "$<PATH:GET_FILENAME,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_FILENAME,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "FILENAME returns bad data: ${output}") +endif() + +compute_reference(EXTENSION) +if (WIN32) + set(output "$<PATH:GET_EXTENSION,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_EXTENSION,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "EXTENSION returns bad data: ${output}") +endif() +compute_reference(EXTENSION LAST_ONLY) +if (WIN32) + set(output "$<PATH:GET_EXTENSION,LAST_ONLY,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_EXTENSION,LAST_ONLY,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "EXTENSION LAST_ONLY returns bad data: ${output}") +endif() + +compute_reference(STEM) +if (WIN32) + set(output "$<PATH:GET_STEM,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_STEM,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "STEM returns bad data: ${output}") +endif() +compute_reference(STEM LAST_ONLY) +if (WIN32) + set(output "$<PATH:GET_STEM,LAST_ONLY,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_STEM,LAST_ONLY,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "STEM LAST_ONLY returns bad data: ${reference}") +endif() + +compute_reference(RELATIVE_PART) +if (WIN32) + set(output "$<PATH:GET_RELATIVE_PART,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_RELATIVE_PART,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "RELATIVE_PART returns bad data: ${output}") +endif() + +compute_reference(PARENT_PATH) +if (WIN32) + set(output "$<PATH:GET_PARENT_PATH,C:/aa/bb/cc.ext1.ext2;D:/xx/yy/zz.ext3.ext4>") +else() + set (output "$<PATH:GET_PARENT_PATH,/aa/bb/cc.ext1.ext2;/xx/yy/zz.ext3.ext4>") +endif() +if (NOT output STREQUAL reference) + list (APPEND errors "PARENT_PATH returns bad data: ${output}") +endif() + + check_errors("PATH:GET..." ${errors}) diff --git a/Tests/RunCMake/GenEx-PATH/NORMAL_PATH.cmake.in b/Tests/RunCMake/GenEx-PATH/NORMAL_PATH.cmake.in index e6cc4a3..81e4c0d 100644 --- a/Tests/RunCMake/GenEx-PATH/NORMAL_PATH.cmake.in +++ b/Tests/RunCMake/GenEx-PATH/NORMAL_PATH.cmake.in @@ -40,4 +40,18 @@ if (WIN32) endif() +###################################### +## tests with list of paths +###################################### +unset (reference) +foreach(item IN ITEMS "a/./b/.." "x/.//y/z//..") + cmake_path(NORMAL_PATH item) + list(APPEND reference "${item}") +endforeach() +set(output "$<PATH:NORMAL_PATH,a/./b/..;x/.//y/z//..>") +if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") +endif() + + check_errors("PATH:NORMAL_PATH" ${errors}) diff --git a/Tests/RunCMake/GenEx-PATH/RELATIVE_PATH.cmake.in b/Tests/RunCMake/GenEx-PATH/RELATIVE_PATH.cmake.in index 11d73ad..7670f4f 100644 --- a/Tests/RunCMake/GenEx-PATH/RELATIVE_PATH.cmake.in +++ b/Tests/RunCMake/GenEx-PATH/RELATIVE_PATH.cmake.in @@ -61,4 +61,18 @@ if (WIN32) endif() +###################################### +## tests with list of paths +###################################### +unset (reference) +foreach(item IN ITEMS "/a//d" "/a/b/e") + cmake_path(RELATIVE_PATH item BASE_DIRECTORY "/a/b/c") + list(APPEND reference "${item}") +endforeach() +set(output "$<PATH:RELATIVE_PATH,/a//d;/a/b/e,/a/b/c>") +if (NOT output STREQUAL reference) + list (APPEND errors "'${output}' instead of '${reference}'") +endif() + + check_errors("PATH:RELATIVE_PATH" ${errors}) diff --git a/Tests/RunCMake/GenEx-PATH/REMOVE_ITEM.cmake.in b/Tests/RunCMake/GenEx-PATH/REMOVE_ITEM.cmake.in index cce4143..a365efe 100644 --- a/Tests/RunCMake/GenEx-PATH/REMOVE_ITEM.cmake.in +++ b/Tests/RunCMake/GenEx-PATH/REMOVE_ITEM.cmake.in @@ -1,3 +1,4 @@ +cmake_policy(SET CMP0140 NEW) include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") unset (errors) @@ -62,4 +63,39 @@ if (NOT output STREQUAL reference) endif() +###################################### +## tests with list of paths +###################################### +function (compute_reference action) + unset(reference) + foreach (path IN LISTS paths) + cmake_path(${action} path ${ARGN}) + list(APPEND reference "${path}") + endforeach() + + return(PROPAGATE reference) +endfunction() + +set (paths "a/b/c.e.f" "g/h/i.j.k") +compute_reference(REMOVE_FILENAME) +set(output "$<PATH:REMOVE_FILENAME,a/b/c.e.f;g/h/i.j.k>") +if (NOT output STREQUAL reference) + list (APPEND errors "FILENAME: '${output}' instead of '${reference}'") +endif() + +set (paths "a/b/c.e.f" "g/h/i.j.k") +compute_reference(REMOVE_EXTENSION) +set(output "$<PATH:REMOVE_EXTENSION,a/b/c.e.f;g/h/i.j.k>") +if (NOT output STREQUAL reference) + list (APPEND errors "EXTENSION: '${output}' instead of '${reference}'") +endif() + +set (reference "a/b/c.e.f" "g/h/i.j.k") +compute_reference(REMOVE_EXTENSION LAST_ONLY) +set(output "$<PATH:REMOVE_EXTENSION,LAST_ONLY,a/b/c.e.f;g/h/i.j.k>") +if (NOT output STREQUAL reference) + list (APPEND errors "EXTENSION: '${output}' instead of '${reference}'") +endif() + + check_errors("PATH:REMOVE..." ${errors}) diff --git a/Tests/RunCMake/GenEx-PATH/REPLACE_ITEM.cmake.in b/Tests/RunCMake/GenEx-PATH/REPLACE_ITEM.cmake.in index 5bb04c3..2d02152 100644 --- a/Tests/RunCMake/GenEx-PATH/REPLACE_ITEM.cmake.in +++ b/Tests/RunCMake/GenEx-PATH/REPLACE_ITEM.cmake.in @@ -1,3 +1,4 @@ +cmake_policy(SET CMP0140 NEW) include ("${RunCMake_SOURCE_DIR}/check_errors.cmake") unset (errors) @@ -70,4 +71,39 @@ if (NOT output STREQUAL reference) endif() +###################################### +## tests with list of paths +###################################### +function (compute_reference action new_value) + unset(reference) + foreach (path IN LISTS paths) + cmake_path(${action} path "${new_value}" ${ARGN}) + list(APPEND reference "${path}") + endforeach() + + return(PROPAGATE reference) +endfunction() + +set (paths "a/b/c.e.f" "g/h/i.j.k") +compute_reference(REPLACE_FILENAME "x.y") +set(output "$<PATH:REPLACE_FILENAME,a/b/c.e.f;g/h/i.j.k,x.y>") +if (NOT output STREQUAL reference) + list (APPEND errors "FILENAME: '${output}' instead of '${reference}'") +endif() + +set (paths "a/b/c.e.f" "g/h/i.j.k") +compute_reference(REPLACE_EXTENSION ".x") +set(output "$<PATH:REPLACE_EXTENSION,a/b/c.e.f;g/h/i.j.k,.x>") +if (NOT output STREQUAL reference) + list (APPEND errors "EXTENSION: '${output}' instead of '${reference}'") +endif() + +set (paths "a/b/c.e.f" "g/h/i.j.k") +compute_reference(REPLACE_EXTENSION ".x" LAST_ONLY) +set(output "$<PATH:REPLACE_EXTENSION,LAST_ONLY,a/b/c.e.f;g/h/i.j.k,.x>") +if (NOT output STREQUAL reference) + list (APPEND errors "EXTENSION: '${output}' instead of '${reference}'") +endif() + + check_errors("PATH:REPLACE..." ${errors}) diff --git a/Tests/RunCMake/GenerateExportHeader/GEH.cmake b/Tests/RunCMake/GenerateExportHeader/GEH.cmake index bf9c302..3e35aa3 100644 --- a/Tests/RunCMake/GenerateExportHeader/GEH.cmake +++ b/Tests/RunCMake/GenerateExportHeader/GEH.cmake @@ -100,7 +100,9 @@ if (WIN32 OR CYGWIN) set(_platform Win32-Clang) elseif(MSVC AND COMPILER_HAS_DEPRECATED) set(_platform Win32) - elseif((MINGW OR CYGWIN) AND COMPILER_HAS_DEPRECATED) + elseif(CYGWIN AND COMPILER_HAS_DEPRECATED) + set(_platform Cygwin) + elseif(MINGW AND COMPILER_HAS_DEPRECATED) set(_platform MinGW) else() set(_platform WinEmpty) diff --git a/Tests/RunCMake/GenerateExportHeader/reference/Cygwin/libshared_export.h b/Tests/RunCMake/GenerateExportHeader/reference/Cygwin/libshared_export.h new file mode 100644 index 0000000..dac4fda --- /dev/null +++ b/Tests/RunCMake/GenerateExportHeader/reference/Cygwin/libshared_export.h @@ -0,0 +1,42 @@ + +#ifndef LIBSHARED_EXPORT_H +#define LIBSHARED_EXPORT_H + +#ifdef LIBSHARED_STATIC_DEFINE +# define LIBSHARED_EXPORT +# define LIBSHARED_NO_EXPORT +#else +# ifndef LIBSHARED_EXPORT +# ifdef libshared_EXPORTS + /* We are building this library */ +# define LIBSHARED_EXPORT __declspec(dllexport) +# else + /* We are using this library */ +# define LIBSHARED_EXPORT __declspec(dllimport) +# endif +# endif + +# ifndef LIBSHARED_NO_EXPORT +# define LIBSHARED_NO_EXPORT +# endif +#endif + +#ifndef LIBSHARED_DEPRECATED +# define LIBSHARED_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef LIBSHARED_DEPRECATED_EXPORT +# define LIBSHARED_DEPRECATED_EXPORT LIBSHARED_EXPORT LIBSHARED_DEPRECATED +#endif + +#ifndef LIBSHARED_DEPRECATED_NO_EXPORT +# define LIBSHARED_DEPRECATED_NO_EXPORT LIBSHARED_NO_EXPORT LIBSHARED_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef LIBSHARED_NO_DEPRECATED +# define LIBSHARED_NO_DEPRECATED +# endif +#endif + +#endif /* LIBSHARED_EXPORT_H */ diff --git a/Tests/RunCMake/GenerateExportHeader/reference/Cygwin/libstatic_export.h b/Tests/RunCMake/GenerateExportHeader/reference/Cygwin/libstatic_export.h new file mode 100644 index 0000000..b6e2a4a --- /dev/null +++ b/Tests/RunCMake/GenerateExportHeader/reference/Cygwin/libstatic_export.h @@ -0,0 +1,42 @@ + +#ifndef LIBSTATIC_EXPORT_H +#define LIBSTATIC_EXPORT_H + +#ifdef LIBSTATIC_STATIC_DEFINE +# define LIBSTATIC_EXPORT +# define LIBSTATIC_NO_EXPORT +#else +# ifndef LIBSTATIC_EXPORT +# ifdef libstatic_EXPORTS + /* We are building this library */ +# define LIBSTATIC_EXPORT +# else + /* We are using this library */ +# define LIBSTATIC_EXPORT +# endif +# endif + +# ifndef LIBSTATIC_NO_EXPORT +# define LIBSTATIC_NO_EXPORT +# endif +#endif + +#ifndef LIBSTATIC_DEPRECATED +# define LIBSTATIC_DEPRECATED __attribute__ ((__deprecated__)) +#endif + +#ifndef LIBSTATIC_DEPRECATED_EXPORT +# define LIBSTATIC_DEPRECATED_EXPORT LIBSTATIC_EXPORT LIBSTATIC_DEPRECATED +#endif + +#ifndef LIBSTATIC_DEPRECATED_NO_EXPORT +# define LIBSTATIC_DEPRECATED_NO_EXPORT LIBSTATIC_NO_EXPORT LIBSTATIC_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef LIBSTATIC_NO_DEPRECATED +# define LIBSTATIC_NO_DEPRECATED +# endif +#endif + +#endif /* LIBSTATIC_EXPORT_H */ diff --git a/Tests/RunCMake/GenerateExportHeader/reference/MinGW/libshared_export.h b/Tests/RunCMake/GenerateExportHeader/reference/MinGW/libshared_export.h index dac4fda..3ba2d2e 100644 --- a/Tests/RunCMake/GenerateExportHeader/reference/MinGW/libshared_export.h +++ b/Tests/RunCMake/GenerateExportHeader/reference/MinGW/libshared_export.h @@ -22,7 +22,7 @@ #endif #ifndef LIBSHARED_DEPRECATED -# define LIBSHARED_DEPRECATED __attribute__ ((__deprecated__)) +# define LIBSHARED_DEPRECATED __declspec(deprecated) #endif #ifndef LIBSHARED_DEPRECATED_EXPORT diff --git a/Tests/RunCMake/GenerateExportHeader/reference/MinGW/libstatic_export.h b/Tests/RunCMake/GenerateExportHeader/reference/MinGW/libstatic_export.h index b6e2a4a..3c7e093 100644 --- a/Tests/RunCMake/GenerateExportHeader/reference/MinGW/libstatic_export.h +++ b/Tests/RunCMake/GenerateExportHeader/reference/MinGW/libstatic_export.h @@ -22,7 +22,7 @@ #endif #ifndef LIBSTATIC_DEPRECATED -# define LIBSTATIC_DEPRECATED __attribute__ ((__deprecated__)) +# define LIBSTATIC_DEPRECATED __declspec(deprecated) #endif #ifndef LIBSTATIC_DEPRECATED_EXPORT diff --git a/Tests/RunCMake/GenerateExportHeader/reference/Win32-Clang/libshared_export.h b/Tests/RunCMake/GenerateExportHeader/reference/Win32-Clang/libshared_export.h index dac4fda..3ba2d2e 100644 --- a/Tests/RunCMake/GenerateExportHeader/reference/Win32-Clang/libshared_export.h +++ b/Tests/RunCMake/GenerateExportHeader/reference/Win32-Clang/libshared_export.h @@ -22,7 +22,7 @@ #endif #ifndef LIBSHARED_DEPRECATED -# define LIBSHARED_DEPRECATED __attribute__ ((__deprecated__)) +# define LIBSHARED_DEPRECATED __declspec(deprecated) #endif #ifndef LIBSHARED_DEPRECATED_EXPORT diff --git a/Tests/RunCMake/GenerateExportHeader/reference/Win32-Clang/libstatic_export.h b/Tests/RunCMake/GenerateExportHeader/reference/Win32-Clang/libstatic_export.h index b6e2a4a..3c7e093 100644 --- a/Tests/RunCMake/GenerateExportHeader/reference/Win32-Clang/libstatic_export.h +++ b/Tests/RunCMake/GenerateExportHeader/reference/Win32-Clang/libstatic_export.h @@ -22,7 +22,7 @@ #endif #ifndef LIBSTATIC_DEPRECATED -# define LIBSTATIC_DEPRECATED __attribute__ ((__deprecated__)) +# define LIBSTATIC_DEPRECATED __declspec(deprecated) #endif #ifndef LIBSTATIC_DEPRECATED_EXPORT diff --git a/Tests/RunCMake/find_package/CMP0144-NEW-CaseInsensitive-stderr.txt b/Tests/RunCMake/find_package/CMP0144-NEW-CaseInsensitive-stderr.txt new file mode 100644 index 0000000..3ccd101 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-NEW-CaseInsensitive-stderr.txt @@ -0,0 +1,45 @@ +^---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/cmake_root/include +FOO_TEST_PATH_ZOT: <base>/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/cmake_root/bin/foo.exe + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/cmake_root/include +FOO_TEST_PATH_ZOT: <base>/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/cmake_root/bin/foo.exe + +---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/env_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/env_root/include +FOO_TEST_PATH_ZOT: <base>/foo/env_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/env_root/bin/foo.exe + +----------$ diff --git a/Tests/RunCMake/find_package/CMP0144-NEW-CaseInsensitive.cmake b/Tests/RunCMake/find_package/CMP0144-NEW-CaseInsensitive.cmake new file mode 100644 index 0000000..f0853ee --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-NEW-CaseInsensitive.cmake @@ -0,0 +1,3 @@ +cmake_policy(VERSION 3.26) +cmake_policy(SET CMP0144 NEW) +include(CMP0144-common.cmake) diff --git a/Tests/RunCMake/find_package/CMP0144-NEW-CaseSensitive-stderr.txt b/Tests/RunCMake/find_package/CMP0144-NEW-CaseSensitive-stderr.txt new file mode 100644 index 0000000..3ccd101 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-NEW-CaseSensitive-stderr.txt @@ -0,0 +1,45 @@ +^---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/cmake_root/include +FOO_TEST_PATH_ZOT: <base>/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/cmake_root/bin/foo.exe + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/cmake_root/include +FOO_TEST_PATH_ZOT: <base>/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/cmake_root/bin/foo.exe + +---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/env_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/env_root/include +FOO_TEST_PATH_ZOT: <base>/foo/env_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/env_root/bin/foo.exe + +----------$ diff --git a/Tests/RunCMake/find_package/CMP0144-NEW-CaseSensitive.cmake b/Tests/RunCMake/find_package/CMP0144-NEW-CaseSensitive.cmake new file mode 100644 index 0000000..f0853ee --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-NEW-CaseSensitive.cmake @@ -0,0 +1,3 @@ +cmake_policy(VERSION 3.26) +cmake_policy(SET CMP0144 NEW) +include(CMP0144-common.cmake) diff --git a/Tests/RunCMake/find_package/CMP0144-OLD-CaseInsensitive-stderr.txt b/Tests/RunCMake/find_package/CMP0144-OLD-CaseInsensitive-stderr.txt new file mode 100644 index 0000000..3274b82 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-OLD-CaseInsensitive-stderr.txt @@ -0,0 +1,45 @@ +^---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/env_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/env_root/include +FOO_TEST_PATH_ZOT: <base>/foo/env_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/env_root/bin/foo.exe + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/env_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/env_root/include +FOO_TEST_PATH_ZOT: <base>/foo/env_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/env_root/bin/foo.exe + +----------$ diff --git a/Tests/RunCMake/find_package/CMP0144-OLD-CaseInsensitive.cmake b/Tests/RunCMake/find_package/CMP0144-OLD-CaseInsensitive.cmake new file mode 100644 index 0000000..f1560a9 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-OLD-CaseInsensitive.cmake @@ -0,0 +1,3 @@ +cmake_policy(VERSION 3.26) +cmake_policy(SET CMP0144 OLD) +include(CMP0144-common.cmake) diff --git a/Tests/RunCMake/find_package/CMP0144-OLD-CaseSensitive-stderr.txt b/Tests/RunCMake/find_package/CMP0144-OLD-CaseSensitive-stderr.txt new file mode 100644 index 0000000..c02a797 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-OLD-CaseSensitive-stderr.txt @@ -0,0 +1,45 @@ +^---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +----------$ diff --git a/Tests/RunCMake/find_package/CMP0144-OLD-CaseSensitive.cmake b/Tests/RunCMake/find_package/CMP0144-OLD-CaseSensitive.cmake new file mode 100644 index 0000000..f1560a9 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-OLD-CaseSensitive.cmake @@ -0,0 +1,3 @@ +cmake_policy(VERSION 3.26) +cmake_policy(SET CMP0144 OLD) +include(CMP0144-common.cmake) diff --git a/Tests/RunCMake/find_package/CMP0144-WARN-CaseInsensitive-stderr.txt b/Tests/RunCMake/find_package/CMP0144-WARN-CaseInsensitive-stderr.txt new file mode 100644 index 0000000..3540dc9 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-WARN-CaseInsensitive-stderr.txt @@ -0,0 +1,63 @@ +^---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '<base>/foo/env_root' ++ +CMake Warning \(dev\) at CMP0144-common.cmake:[0-9]+ \(find_package\): + Policy CMP0144 is not set: find_package uses upper-case <PACKAGENAME>_ROOT + variables. Run "cmake --help-policy CMP0144" for policy details\. Use the + cmake_policy command to set the policy and suppress this warning\. + + CMake variable FOO_ROOT is set to: + + [^ +]*/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root + + For compatibility, find_package is ignoring the variable, but code in a + \.cmake module might still use it\. +Call Stack \(most recent call first\): + CMP0144-common.cmake:[0-9]+ \(RunTestCase\) + CMP0144-WARN-CaseInsensitive.cmake:[0-9]+ \(include\) + CMakeLists.txt:[0-9]+ \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. ++ +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/env_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/env_root/include +FOO_TEST_PATH_ZOT: <base>/foo/env_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/env_root/bin/foo.exe + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/env_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/env_root/include +FOO_TEST_PATH_ZOT: <base>/foo/env_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/env_root/bin/foo.exe + +----------$ diff --git a/Tests/RunCMake/find_package/CMP0144-WARN-CaseInsensitive.cmake b/Tests/RunCMake/find_package/CMP0144-WARN-CaseInsensitive.cmake new file mode 100644 index 0000000..10f6b66 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-WARN-CaseInsensitive.cmake @@ -0,0 +1,3 @@ +cmake_policy(VERSION 3.26) +# (do not set CMP0144) +include(CMP0144-common.cmake) diff --git a/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive-Mixed-stderr.txt b/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive-Mixed-stderr.txt new file mode 100644 index 0000000..3ccd101 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive-Mixed-stderr.txt @@ -0,0 +1,45 @@ +^---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/cmake_root/include +FOO_TEST_PATH_ZOT: <base>/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/cmake_root/bin/foo.exe + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/cmake_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/cmake_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/cmake_root/include +FOO_TEST_PATH_ZOT: <base>/foo/cmake_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/cmake_root/bin/foo.exe + +---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: <base>/foo/env_root/include/foo.h +FOO_TEST_FILE_ZOT: <base>/foo/env_root/include/zot/zot.h +FOO_TEST_PATH_FOO: <base>/foo/env_root/include +FOO_TEST_PATH_ZOT: <base>/foo/env_root/include/zot +FOO_TEST_PROG_FOO: <base>/foo/env_root/bin/foo.exe + +----------$ diff --git a/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive-Mixed.cmake b/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive-Mixed.cmake new file mode 100644 index 0000000..10f6b66 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive-Mixed.cmake @@ -0,0 +1,3 @@ +cmake_policy(VERSION 3.26) +# (do not set CMP0144) +include(CMP0144-common.cmake) diff --git a/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive-stderr.txt b/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive-stderr.txt new file mode 100644 index 0000000..b828f05 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive-stderr.txt @@ -0,0 +1,68 @@ +^---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '<base>/foo/env_root' ++ +CMake Warning \(dev\) at CMP0144-common.cmake:[0-9]+ \(find_package\): + Policy CMP0144 is not set: find_package uses upper-case <PACKAGENAME>_ROOT + variables. Run "cmake --help-policy CMP0144" for policy details\. Use the + cmake_policy command to set the policy and suppress this warning\. + + CMake variable FOO_ROOT is set to: + + [^ +]*/Tests/RunCMake/find_package/PackageRoot/foo/cmake_root + + Environment variable FOO_ROOT is set to: + + [^ +]*/Tests/RunCMake/find_package/PackageRoot/foo/env_root + + For compatibility, find_package is ignoring the variable, but code in a + \.cmake module might still use it\. +Call Stack \(most recent call first\): + CMP0144-common.cmake:[0-9]+ \(RunTestCase\) + CMP0144-WARN-CaseSensitive.cmake:[0-9]+ \(include\) + CMakeLists.txt:[0-9]+ \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. ++ +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '<base>/foo/cmake_root' +ENV{FOO_ROOT}: '' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +---------- +FOO_ROOT : '' +ENV{FOO_ROOT}: '<base>/foo/env_root' + +find_package\(Foo\) +FOO_TEST_FILE_FOO: FOO_TEST_FILE_FOO-NOTFOUND +FOO_TEST_FILE_ZOT: FOO_TEST_FILE_ZOT-NOTFOUND +FOO_TEST_PATH_FOO: FOO_TEST_PATH_FOO-NOTFOUND +FOO_TEST_PATH_ZOT: FOO_TEST_PATH_ZOT-NOTFOUND +FOO_TEST_PROG_FOO: FOO_TEST_PROG_FOO-NOTFOUND + +----------$ diff --git a/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive.cmake b/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive.cmake new file mode 100644 index 0000000..10f6b66 --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-WARN-CaseSensitive.cmake @@ -0,0 +1,3 @@ +cmake_policy(VERSION 3.26) +# (do not set CMP0144) +include(CMP0144-common.cmake) diff --git a/Tests/RunCMake/find_package/CMP0144-common.cmake b/Tests/RunCMake/find_package/CMP0144-common.cmake new file mode 100644 index 0000000..58eccca --- /dev/null +++ b/Tests/RunCMake/find_package/CMP0144-common.cmake @@ -0,0 +1,78 @@ +# (includer selects CMP0144) +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot) +set(PackageRoot_BASE ${CMAKE_CURRENT_SOURCE_DIR}/PackageRoot) + +function(PrintPath label path) + string(REPLACE "${PackageRoot_BASE}" "<base>" out "${path}") + message("${label} ${out}") +endfunction() + +macro(RunTestCase) + message("----------") + PrintPath("FOO_ROOT :" "'${FOO_ROOT}'") + PrintPath("ENV{FOO_ROOT}:" "'$ENV{FOO_ROOT}'") + message("") + + find_package(Foo) + message("find_package(Foo)") + PrintPath("FOO_TEST_FILE_FOO:" "${FOO_TEST_FILE_FOO}") + PrintPath("FOO_TEST_FILE_ZOT:" "${FOO_TEST_FILE_ZOT}") + PrintPath("FOO_TEST_PATH_FOO:" "${FOO_TEST_PATH_FOO}") + PrintPath("FOO_TEST_PATH_ZOT:" "${FOO_TEST_PATH_ZOT}") + PrintPath("FOO_TEST_PROG_FOO:" "${FOO_TEST_PROG_FOO}") + message("") + + unset(FOO_ROOT) + unset(ENV{FOO_ROOT}) + if(NOT CMAKE_HOST_WIN32) + unset(Foo_ROOT) + unset(ENV{Foo_ROOT}) + endif() + unset(FOO_TEST_FILE_FOO) + unset(FOO_TEST_FILE_ZOT) + unset(FOO_TEST_PATH_FOO) + unset(FOO_TEST_PATH_ZOT) + unset(FOO_TEST_PROG_FOO) + unset(FOO_TEST_FILE_FOO CACHE) + unset(FOO_TEST_FILE_ZOT CACHE) + unset(FOO_TEST_PATH_FOO CACHE) + unset(FOO_TEST_PATH_ZOT CACHE) + unset(FOO_TEST_PROG_FOO CACHE) +endmacro() + +RunTestCase() + +set(FOO_ROOT ${PackageRoot_BASE}/foo/cmake_root) +set(ENV{FOO_ROOT} ${PackageRoot_BASE}/foo/env_root) +if(RunCMake_TEST MATCHES "CaseSensitive") + if(RunCMake_TEST STREQUAL "CMP0144-WARN-CaseSensitive-Mixed") + set(Foo_ROOT "${FOO_ROOT}") + set(ENV{Foo_ROOT} "$ENV{FOO_ROOT}") + else() + set(Foo_ROOT ${PackageRoot_BASE}/does_not_exist) + set(ENV{Foo_ROOT} ${PackageRoot_BASE}/does_not_exist) + endif() +endif() +RunTestCase() + +set(FOO_ROOT ${PackageRoot_BASE}/foo/cmake_root) +if(RunCMake_TEST MATCHES "CaseSensitive") + if(RunCMake_TEST STREQUAL "CMP0144-WARN-CaseSensitive-Mixed") + set(Foo_ROOT "${FOO_ROOT}") + else() + set(Foo_ROOT ${PackageRoot_BASE}/does_not_exist) + endif() +endif() +RunTestCase() + +set(ENV{FOO_ROOT} ${PackageRoot_BASE}/foo/env_root) +if(RunCMake_TEST MATCHES "CaseSensitive") + if(RunCMake_TEST STREQUAL "CMP0144-WARN-CaseSensitive-Mixed") + set(ENV{Foo_ROOT} "$ENV{FOO_ROOT}") + else() + set(ENV{Foo_ROOT} ${PackageRoot_BASE}/does_not_exist) + endif() +endif() +RunTestCase() + +message("----------") diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index fa41fc1..e7e3a0b 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -55,6 +55,17 @@ run_cmake(REGISTRY_VIEW-no-view) run_cmake(REGISTRY_VIEW-wrong-view) run_cmake(REGISTRY_VIEW-propagated) +if(CMAKE_HOST_WIN32) + run_cmake(CMP0144-WARN-CaseInsensitive) + run_cmake(CMP0144-OLD-CaseInsensitive) + run_cmake(CMP0144-NEW-CaseInsensitive) +else() + run_cmake(CMP0144-WARN-CaseSensitive) + run_cmake(CMP0144-WARN-CaseSensitive-Mixed) + run_cmake(CMP0144-OLD-CaseSensitive) + run_cmake(CMP0144-NEW-CaseSensitive) +endif() + file( GLOB SearchPaths_TEST_CASE_LIST LIST_DIRECTORIES TRUE |