diff options
1637 files changed, 29097 insertions, 10081 deletions
@@ -19,6 +19,7 @@ out/ # Visual Studio Code .vscode/ +.cache/ # CLion work directory .idea/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 65bcd5f..0e5824d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -275,6 +275,26 @@ t:hip4.2-radeon: variables: CMAKE_CI_NO_MR: "true" +t:linux-gcc-cxx-modules-ninja: + extends: + - .gcc_cxx_modules_ninja + - .cmake_test_linux_release + - .linux_builder_tags + - .run_dependent + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + +t:linux-gcc-cxx-modules-ninja-multi: + extends: + - .gcc_cxx_modules_ninja_multi + - .cmake_test_linux_release + - .linux_builder_tags + - .run_dependent + - .needs_centos6_x86_64 + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + b:fedora36-ninja: extends: - .fedora36_ninja @@ -294,6 +314,33 @@ b:debian10-makefiles-inplace: variables: CMAKE_CI_JOB_NIGHTLY: "true" +b:debian10-extdeps: + extends: + - .debian10_extdeps + - .cmake_build_linux_standalone + - .linux_builder_tags + - .run_manually + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + +b:debian10-aarch64-extdeps: + extends: + - .debian10_aarch64_extdeps + - .cmake_build_linux_standalone + - .linux_builder_tags_aarch64 + - .run_manually + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + +b:fedora36-extdeps: + extends: + - .fedora36_extdeps + - .cmake_build_linux_standalone + - .linux_builder_tags + - .run_manually + variables: + CMAKE_CI_JOB_NIGHTLY: "true" + t:fedora36-ninja: extends: - .fedora36_ninja @@ -544,6 +591,13 @@ t:intel2021.6.0-makefiles: CMAKE_CI_BUILD_NAME: intel2021.6.0_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.1.0-el8 +t:intel2021.7.0-makefiles: + extends: + - .cmake_test_linux_intelclassic_makefiles + variables: + CMAKE_CI_BUILD_NAME: intel2021.7.0_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.2.0-el8 + t:oneapi2021.1.1-makefiles: extends: - .cmake_test_linux_inteloneapi_makefiles @@ -593,6 +647,13 @@ t:oneapi2022.1.0-makefiles: CMAKE_CI_BUILD_NAME: oneapi2022.1.0_makefiles CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.1.0-el8 +t:oneapi2022.2.0-makefiles: + extends: + - .cmake_test_linux_inteloneapi_makefiles + variables: + CMAKE_CI_BUILD_NAME: oneapi2022.2.0_makefiles + CMAKE_CI_INTELCOMPILER_IMAGE_TAG: 2022.2.0-el8 + b:linux-x86_64-package: extends: - .linux_package diff --git a/.gitlab/.gitignore b/.gitlab/.gitignore new file mode 100644 index 0000000..d62e477 --- /dev/null +++ b/.gitlab/.gitignore @@ -0,0 +1,16 @@ +# Ignore files known to be downloaded by CI jobs. +/5.15.1-0-202009071110* +/bcc* +/cmake* +/ispc* +/jom +/llvm* +/msvc* +/ninja* +/open-watcom* +/python* +/qt* +/sccache* +/unstable-jom* +/watcom +/wix* diff --git a/.gitlab/ci/configure_debian10_aarch64_extdeps.cmake b/.gitlab/ci/configure_debian10_aarch64_extdeps.cmake new file mode 100644 index 0000000..8e545f5 --- /dev/null +++ b/.gitlab/ci/configure_debian10_aarch64_extdeps.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_extdeps_common.cmake") diff --git a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake index bbccbcf..605f6ba 100644 --- a/.gitlab/ci/configure_debian10_aarch64_ninja.cmake +++ b/.gitlab/ci/configure_debian10_aarch64_ninja.cmake @@ -44,11 +44,13 @@ set(CMake_TEST_FindMPI_Fortran "ON" CACHE BOOL "") set(CMake_TEST_FindMPI "ON" CACHE BOOL "") set(CMake_TEST_FindODBC "ON" CACHE BOOL "") set(CMake_TEST_FindOpenACC "ON" CACHE BOOL "") +set(CMake_TEST_FindOpenAL "ON" CACHE BOOL "") set(CMake_TEST_FindOpenGL "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP_C "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP_CXX "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP_Fortran "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP "ON" CACHE BOOL "") +set(CMake_TEST_FindOpenSP "ON" CACHE BOOL "") set(CMake_TEST_FindOpenSSL "ON" CACHE BOOL "") set(CMake_TEST_FindPatch "ON" CACHE BOOL "") set(CMake_TEST_FindPNG "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_debian10_extdeps.cmake b/.gitlab/ci/configure_debian10_extdeps.cmake new file mode 100644 index 0000000..8e545f5 --- /dev/null +++ b/.gitlab/ci/configure_debian10_extdeps.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_extdeps_common.cmake") diff --git a/.gitlab/ci/configure_debian10_ninja.cmake b/.gitlab/ci/configure_debian10_ninja.cmake index 2fcff7a..214828a 100644 --- a/.gitlab/ci/configure_debian10_ninja.cmake +++ b/.gitlab/ci/configure_debian10_ninja.cmake @@ -48,11 +48,13 @@ set(CMake_TEST_FindMPI_Fortran "ON" CACHE BOOL "") set(CMake_TEST_FindMPI "ON" CACHE BOOL "") set(CMake_TEST_FindODBC "ON" CACHE BOOL "") set(CMake_TEST_FindOpenACC "ON" CACHE BOOL "") +set(CMake_TEST_FindOpenAL "ON" CACHE BOOL "") set(CMake_TEST_FindOpenGL "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP_C "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP_CXX "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP_Fortran "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP "ON" CACHE BOOL "") +set(CMake_TEST_FindOpenSP "ON" CACHE BOOL "") set(CMake_TEST_FindOpenSSL "ON" CACHE BOOL "") set(CMake_TEST_FindPatch "ON" CACHE BOOL "") set(CMake_TEST_FindPNG "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_extdeps_common.cmake b/.gitlab/ci/configure_extdeps_common.cmake new file mode 100644 index 0000000..2c7d328 --- /dev/null +++ b/.gitlab/ci/configure_extdeps_common.cmake @@ -0,0 +1,5 @@ +set(CMAKE_USE_SYSTEM_LIBRARIES ON CACHE BOOL "") +set(CMAKE_SKIP_BOOTSTRAP_TEST ON CACHE BOOL "") +set(CMake_TEST_Qt6 OFF CACHE BOOL "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_common.cmake") diff --git a/.gitlab/ci/configure_fedora36_extdeps.cmake b/.gitlab/ci/configure_fedora36_extdeps.cmake new file mode 100644 index 0000000..8e545f5 --- /dev/null +++ b/.gitlab/ci/configure_fedora36_extdeps.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/configure_extdeps_common.cmake") diff --git a/.gitlab/ci/configure_fedora36_makefiles.cmake b/.gitlab/ci/configure_fedora36_makefiles.cmake index c5b5190..11d1a08 100644 --- a/.gitlab/ci/configure_fedora36_makefiles.cmake +++ b/.gitlab/ci/configure_fedora36_makefiles.cmake @@ -47,11 +47,13 @@ set(CMake_TEST_FindMPI_Fortran "ON" CACHE BOOL "") set(CMake_TEST_FindMPI "ON" CACHE BOOL "") set(CMake_TEST_FindODBC "ON" CACHE BOOL "") set(CMake_TEST_FindOpenACC "ON" CACHE BOOL "") +set(CMake_TEST_FindOpenAL "ON" CACHE BOOL "") set(CMake_TEST_FindOpenGL "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP_C "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP_CXX "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP_Fortran "ON" CACHE BOOL "") set(CMake_TEST_FindOpenMP "ON" CACHE BOOL "") +set(CMake_TEST_FindOpenSP "ON" CACHE BOOL "") set(CMake_TEST_FindOpenSSL "ON" CACHE BOOL "") set(CMake_TEST_FindPatch "ON" CACHE BOOL "") set(CMake_TEST_FindPNG "ON" CACHE BOOL "") diff --git a/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake new file mode 100644 index 0000000..2b04e89 --- /dev/null +++ b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja.cmake @@ -0,0 +1,4 @@ +set(CMake_TEST_MODULE_COMPILATION "named,partitions,internal_partitions,export_bmi,install_bmi" CACHE STRING "") +set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_gcc.cmake" CACHE STRING "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake new file mode 100644 index 0000000..2b04e89 --- /dev/null +++ b/.gitlab/ci/configure_linux_gcc_cxx_modules_ninja_multi.cmake @@ -0,0 +1,4 @@ +set(CMake_TEST_MODULE_COMPILATION "named,partitions,internal_partitions,export_bmi,install_bmi" CACHE STRING "") +set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_gcc.cmake" CACHE STRING "") + +include("${CMAKE_CURRENT_LIST_DIR}/configure_external_test.cmake") diff --git a/.gitlab/ci/configure_windows_msvc_cxx_modules_common.cmake b/.gitlab/ci/configure_windows_msvc_cxx_modules_common.cmake new file mode 100644 index 0000000..8570196 --- /dev/null +++ b/.gitlab/ci/configure_windows_msvc_cxx_modules_common.cmake @@ -0,0 +1,2 @@ +set(CMake_TEST_MODULE_COMPILATION "named,partitions,internal_partitions,shared,export_bmi,install_bmi" CACHE STRING "") +set(CMake_TEST_MODULE_COMPILATION_RULES "${CMAKE_CURRENT_LIST_DIR}/cxx_modules_rules_msvc.cmake" CACHE STRING "") diff --git a/.gitlab/ci/configure_windows_vs2022_x64_ninja.cmake b/.gitlab/ci/configure_windows_vs2022_x64_ninja.cmake index 7f57181..f5a6d80 100644 --- a/.gitlab/ci/configure_windows_vs2022_x64_ninja.cmake +++ b/.gitlab/ci/configure_windows_vs2022_x64_ninja.cmake @@ -2,4 +2,5 @@ if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "") set(CMake_TEST_ISPC "ON" CACHE STRING "") endif() +include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_msvc_cxx_modules_common.cmake") include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_vs_common_ninja.cmake") diff --git a/.gitlab/ci/configure_windows_vs2022_x64_ninja_multi.cmake b/.gitlab/ci/configure_windows_vs2022_x64_ninja_multi.cmake index 5b2f0b7..2b0c76d 100644 --- a/.gitlab/ci/configure_windows_vs2022_x64_ninja_multi.cmake +++ b/.gitlab/ci/configure_windows_vs2022_x64_ninja_multi.cmake @@ -2,4 +2,5 @@ if (NOT "$ENV{CMAKE_CI_NIGHTLY}" STREQUAL "") set(CMake_TEST_ISPC "ON" CACHE STRING "") endif() +include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_msvc_cxx_modules_common.cmake") include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_msvc_common.cmake") diff --git a/.gitlab/ci/ctest_standalone.cmake b/.gitlab/ci/ctest_standalone.cmake index 9199693..36ba71c 100644 --- a/.gitlab/ci/ctest_standalone.cmake +++ b/.gitlab/ci/ctest_standalone.cmake @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.8) include("${CMAKE_CURRENT_LIST_DIR}/gitlab_ci.cmake") include("${CMAKE_CURRENT_LIST_DIR}/env_$ENV{CMAKE_CONFIGURATION}.cmake" OPTIONAL) -set(cmake_args - -C "${CMAKE_CURRENT_LIST_DIR}/configure_$ENV{CMAKE_CONFIGURATION}.cmake") +set(initial_cache "${CMAKE_CURRENT_LIST_DIR}/configure_$ENV{CMAKE_CONFIGURATION}.cmake") +set(cmake_args -C "${initial_cache}") include(ProcessorCount) ProcessorCount(nproc) @@ -25,6 +25,8 @@ ctest_update() if("$ENV{CMAKE_CI_BOOTSTRAP}") set(CTEST_CONFIGURE_COMMAND "\"${CTEST_SOURCE_DIRECTORY}/bootstrap\" --parallel=${nproc}") +elseif("$ENV{CMAKE_CONFIGURATION}" MATCHES "extdeps") + set(CTEST_CONFIGURE_COMMAND "/opt/extdeps/bin/cmake -C \"${initial_cache}\" -G \"${CTEST_CMAKE_GENERATOR}\" \"${CTEST_SOURCE_DIRECTORY}\"") endif() # Configure the project. diff --git a/.gitlab/ci/cxx_modules_rules_gcc.cmake b/.gitlab/ci/cxx_modules_rules_gcc.cmake new file mode 100644 index 0000000..d800099 --- /dev/null +++ b/.gitlab/ci/cxx_modules_rules_gcc.cmake @@ -0,0 +1,10 @@ +set(CMake_TEST_CXXModules_UUID "a246741c-d067-4019-a8fb-3d16b0c9d1d3") + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE + "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E -x c++ <SOURCE>" + " -MT <DYNDEP_FILE> -MD -MF <DEP_FILE>" + " -fmodules-ts -fdep-file=<DYNDEP_FILE> -fdep-output=<OBJECT> -fdep-format=trtbd" + " -o <PREPROCESSED_SOURCE>") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "gcc") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "-fmodules-ts -fmodule-mapper=<MODULE_MAP_FILE> -fdep-format=trtbd -x c++") diff --git a/.gitlab/ci/cxx_modules_rules_msvc.cmake b/.gitlab/ci/cxx_modules_rules_msvc.cmake new file mode 100644 index 0000000..5f0ae76 --- /dev/null +++ b/.gitlab/ci/cxx_modules_rules_msvc.cmake @@ -0,0 +1,11 @@ +set(CMake_TEST_CXXModules_UUID "a246741c-d067-4019-a8fb-3d16b0c9d1d3") + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE + "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> <SOURCE> -nologo -TP" + " -showIncludes" + " -scanDependencies <DYNDEP_FILE>" + " -Fo<OBJECT>") +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_DEPFILE_FORMAT "msvc") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "msvc") +set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>") diff --git a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh index 3dd814d..8b5a001 100755 --- a/.gitlab/ci/docker/debian10-aarch64/install_deps.sh +++ b/.gitlab/ci/docker/debian10-aarch64/install_deps.sh @@ -14,6 +14,20 @@ apt-get install -y \ curl \ git +# Install optional external build dependencies. +apt-get install -y \ + libarchive-dev \ + libbz2-dev \ + libcurl4-gnutls-dev \ + libexpat1-dev \ + libjsoncpp-dev \ + liblzma-dev \ + libncurses-dev \ + librhash-dev \ + libuv1-dev \ + libzstd-dev \ + zlib1g-dev + # Install iwyu runtime deps. apt-get install -y \ clang-6.0 \ @@ -66,6 +80,7 @@ apt-get install -y \ liblzma-dev \ libopenal-dev \ libopenmpi-dev openmpi-bin \ + libosp-dev \ libpng-dev \ libpq-dev postgresql-server-dev-11 \ libprotobuf-dev libprotobuf-c-dev libprotoc-dev protobuf-compiler protobuf-compiler-grpc \ diff --git a/.gitlab/ci/docker/debian10/install_deps.sh b/.gitlab/ci/docker/debian10/install_deps.sh index f796816..486b2f7 100755 --- a/.gitlab/ci/docker/debian10/install_deps.sh +++ b/.gitlab/ci/docker/debian10/install_deps.sh @@ -14,6 +14,20 @@ apt-get install -y \ curl \ git +# Install optional external build dependencies. +apt-get install -y \ + libarchive-dev \ + libbz2-dev \ + libcurl4-gnutls-dev \ + libexpat1-dev \ + libjsoncpp-dev \ + liblzma-dev \ + libncurses-dev \ + librhash-dev \ + libuv1-dev \ + libzstd-dev \ + zlib1g-dev + # Install iwyu runtime deps. apt-get install -y \ clang-6.0 \ @@ -70,6 +84,7 @@ apt-get install -y \ liblzma-dev \ libopenal-dev \ libopenmpi-dev openmpi-bin \ + libosp-dev \ libpng-dev \ libpq-dev postgresql-server-dev-11 \ libprotobuf-dev libprotobuf-c-dev libprotoc-dev protobuf-compiler protobuf-compiler-grpc \ diff --git a/.gitlab/ci/docker/fedora36/Dockerfile b/.gitlab/ci/docker/fedora36/Dockerfile index 26f8e3e..ea42561 100644 --- a/.gitlab/ci/docker/fedora36/Dockerfile +++ b/.gitlab/ci/docker/fedora36/Dockerfile @@ -4,6 +4,18 @@ MAINTAINER Ben Boeckel <ben.boeckel@kitware.com> COPY install_rvm.sh /root/install_rvm.sh RUN sh /root/install_rvm.sh +FROM fedora:36 AS clang-tidy-headers +MAINTAINER Kyle Edwards <kyle.edwards@kitware.com> + +COPY install_clang_tidy_headers.sh /root/install_clang_tidy_headers.sh +RUN sh /root/install_clang_tidy_headers.sh + +FROM fedora:36 AS iwyu +MAINTAINER Kyle Edwards <kyle.edwards@kitware.com> + +COPY install_iwyu.sh /root/install_iwyu.sh +RUN sh /root/install_iwyu.sh + FROM fedora:36 MAINTAINER Ben Boeckel <ben.boeckel@kitware.com> @@ -13,3 +25,9 @@ RUN sh /root/install_deps.sh COPY --from=rvm-build /root/rvm.tar /root/rvm.tar RUN tar -C /usr/local -xf /root/rvm.tar \ && rm /root/rvm.tar +COPY --from=clang-tidy-headers /root/clang-tidy-headers.tar /root/clang-tidy-headers.tar +RUN tar -C /usr/include -xf /root/clang-tidy-headers.tar \ + && rm /root/clang-tidy-headers.tar +COPY --from=iwyu /root/iwyu.tar /root/iwyu.tar +RUN tar -C / -xf /root/iwyu.tar \ + && rm /root/iwyu.tar diff --git a/.gitlab/ci/docker/fedora36/install_clang_tidy_headers.sh b/.gitlab/ci/docker/fedora36/install_clang_tidy_headers.sh new file mode 100755 index 0000000..b9883f4 --- /dev/null +++ b/.gitlab/ci/docker/fedora36/install_clang_tidy_headers.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +set -e + +# Packages for building the clang-tidy plugin. +# TODO: Upstream this as a proper Fedora package. +dnf install --setopt=install_weak_deps=False -y \ + 'dnf-command(download)' \ + rpm-build \ + python3-devel \ + clang-tools-extra +clang_source_rpm=$(rpm -q --queryformat '%{SOURCERPM}' clang-tools-extra) +clang_version=$(rpm -q --queryformat '%{VERSION}' clang-tools-extra) +dnf download --source -y clang +rpm -i "$clang_source_rpm" +rpmbuild -bp /root/rpmbuild/SPECS/clang.spec +cd "/root/rpmbuild/BUILD/clang-tools-extra-$clang_version.src" +find clang-tidy -name '*.h' | tar -cf /root/clang-tidy-headers.tar -T - diff --git a/.gitlab/ci/docker/fedora36/install_deps.sh b/.gitlab/ci/docker/fedora36/install_deps.sh index b8ddfb9..f117888 100755 --- a/.gitlab/ci/docker/fedora36/install_deps.sh +++ b/.gitlab/ci/docker/fedora36/install_deps.sh @@ -17,6 +17,20 @@ dnf install --setopt=install_weak_deps=False -y \ git-core \ make +# Install optional external build dependencies. +dnf install --setopt=install_weak_deps=False -y \ + bzip2-devel \ + expat-devel \ + jsoncpp-devel \ + libarchive-devel \ + libcurl-devel \ + libuv-devel \ + libuv-devel \ + libzstd-devel \ + rhash-devel \ + xz-devel \ + zlib-devel + # Install documentation tools. dnf install --setopt=install_weak_deps=False -y \ python3-sphinx \ @@ -78,6 +92,7 @@ dnf install --setopt=install_weak_deps=False -y \ libinput-devel systemd-devel \ libjpeg-turbo-devel \ libpng-devel \ + opensp-devel \ postgresql-server-devel \ libtiff-devel \ libuv-devel \ diff --git a/.gitlab/ci/docker/fedora36/install_iwyu.sh b/.gitlab/ci/docker/fedora36/install_iwyu.sh new file mode 100755 index 0000000..714bcc0 --- /dev/null +++ b/.gitlab/ci/docker/fedora36/install_iwyu.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +set -e + +# Install development tools. +dnf install --setopt=install_weak_deps=False -y \ + clang-devel \ + llvm-devel \ + zlib-devel \ + g++ \ + cmake \ + ninja-build \ + git + +cd /root +git clone "https://github.com/include-what-you-use/include-what-you-use.git" +cd include-what-you-use +readonly llvm_full_version="$( clang --version | head -n1 | cut -d' ' -f3 )" +readonly llvm_version="$( echo "$llvm_full_version" | cut -d. -f-1 )" +git checkout "clang_$llvm_version" +git apply <<EOF +diff --git a/iwyu_driver.cc b/iwyu_driver.cc +index 42fea35..fbb77a9 100644 +--- a/iwyu_driver.cc ++++ b/iwyu_driver.cc +@@ -167,6 +167,7 @@ CompilerInstance* CreateCompilerInstance(int argc, const char **argv) { + DiagnosticsEngine diagnostics(diagnostic_id, &*diagnostic_options, + diagnostic_client); + Driver driver(path, getDefaultTargetTriple(), diagnostics); ++ driver.ResourceDir = "/usr/lib64/clang/$llvm_full_version"; + driver.setTitle("include what you use"); + + // Expand out any response files passed on the command line +EOF +mkdir build +cd build + +cmake -GNinja \ + -DCMAKE_BUILD_TYPE=Release \ + "-DCMAKE_INSTALL_PREFIX=/usr/local/lib64/llvm-$llvm_version" \ + .. +ninja +DESTDIR=/root/iwyu-destdir ninja install +tar -C /root/iwyu-destdir -cf /root/iwyu.tar . diff --git a/.gitlab/ci/docker/gcc_cxx_modules/Dockerfile b/.gitlab/ci/docker/gcc_cxx_modules/Dockerfile new file mode 100644 index 0000000..e0af0b9 --- /dev/null +++ b/.gitlab/ci/docker/gcc_cxx_modules/Dockerfile @@ -0,0 +1,9 @@ +FROM fedora:36 +MAINTAINER Ben Boeckel <ben.boeckel@kitware.com> + +# Install build dependencies for packages. +COPY install_deps.sh /root/install_deps.sh +RUN sh /root/install_deps.sh + +COPY install_gcc.sh /root/install_gcc.sh +RUN sh /root/install_gcc.sh diff --git a/.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh b/.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh new file mode 100755 index 0000000..b8b706b --- /dev/null +++ b/.gitlab/ci/docker/gcc_cxx_modules/install_deps.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +dnf install -y --setopt=install_weak_deps=False \ + gcc-c++ mpfr-devel libmpc-devel isl-devel flex bison file findutils diffutils git-core +dnf clean all diff --git a/.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh b/.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh new file mode 100755 index 0000000..20ea35f --- /dev/null +++ b/.gitlab/ci/docker/gcc_cxx_modules/install_gcc.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +set -e + +readonly revision="p1689r5-cmake-ci-20220614" # 3075e510e3d29583f8886b95aff044c0474c84a5 +readonly tarball="https://github.com/mathstuf/gcc/archive/$revision.tar.gz" + +readonly workdir="$HOME/gcc" +readonly srcdir="$workdir/gcc" +readonly builddir="$workdir/build" +readonly njobs="$( nproc )" + +mkdir -p "$workdir" +cd "$workdir" +curl -L "$tarball" > "gcc-$revision.tar.gz" +tar xf "gcc-$revision.tar.gz" +mv "gcc-$revision" "$srcdir" +mkdir -p "$builddir" +cd "$builddir" +"$srcdir/configure" \ + --disable-multilib \ + --enable-languages=c,c++ \ + --prefix="/opt/gcc-p1689" +make "-j$njobs" +make "-j$njobs" install-strip +rm -rf "$workdir" diff --git a/.gitlab/ci/env.ps1 b/.gitlab/ci/env.ps1 index e24bc37..72a8cb8 100755 --- a/.gitlab/ci/env.ps1 +++ b/.gitlab/ci/env.ps1 @@ -1,3 +1,4 @@ +$pwsh = [System.Diagnostics.Process]::GetCurrentProcess().MainModule.FileName if (Test-Path -Path ".gitlab/ci/env_$env:CMAKE_CONFIGURATION.ps1" -PathType Leaf) { - Invoke-Expression ".gitlab/ci/env_$env:CMAKE_CONFIGURATION.ps1" + . ".gitlab/ci/env_$env:CMAKE_CONFIGURATION.ps1" } diff --git a/.gitlab/ci/env_debian10_aarch64_extdeps.sh b/.gitlab/ci/env_debian10_aarch64_extdeps.sh new file mode 100644 index 0000000..7076e18 --- /dev/null +++ b/.gitlab/ci/env_debian10_aarch64_extdeps.sh @@ -0,0 +1 @@ +source .gitlab/ci/env_extdeps_common.sh diff --git a/.gitlab/ci/env_debian10_extdeps.sh b/.gitlab/ci/env_debian10_extdeps.sh new file mode 100644 index 0000000..7076e18 --- /dev/null +++ b/.gitlab/ci/env_debian10_extdeps.sh @@ -0,0 +1 @@ +source .gitlab/ci/env_extdeps_common.sh diff --git a/.gitlab/ci/env_extdeps_common.sh b/.gitlab/ci/env_extdeps_common.sh new file mode 100644 index 0000000..8cabc05 --- /dev/null +++ b/.gitlab/ci/env_extdeps_common.sh @@ -0,0 +1,5 @@ +.gitlab/ci/extdeps-linux.sh + +export CMAKE_PREFIX_PATH=/opt/extdeps +export PATH=/opt/extdeps/bin:$PATH +export LD_LIBRARY_PATH=/opt/extdeps/lib diff --git a/.gitlab/ci/env_fedora36_extdeps.sh b/.gitlab/ci/env_fedora36_extdeps.sh new file mode 100644 index 0000000..7076e18 --- /dev/null +++ b/.gitlab/ci/env_fedora36_extdeps.sh @@ -0,0 +1 @@ +source .gitlab/ci/env_extdeps_common.sh diff --git a/.gitlab/ci/env_windows_vs2022_x64_ninja.ps1 b/.gitlab/ci/env_windows_vs2022_x64_ninja.ps1 index f8a86c4..a96658d 100755 --- a/.gitlab/ci/env_windows_vs2022_x64_ninja.ps1 +++ b/.gitlab/ci/env_windows_vs2022_x64_ninja.ps1 @@ -1,3 +1,3 @@ if ("$env:CMAKE_CI_NIGHTLY" -eq "true") { - Invoke-Expression ".gitlab/ci/ispc-env.ps1" + . ".gitlab/ci/ispc-env.ps1" } diff --git a/.gitlab/ci/env_windows_vs2022_x64_ninja_multi.ps1 b/.gitlab/ci/env_windows_vs2022_x64_ninja_multi.ps1 index e8d242c..e5f538a 100755 --- a/.gitlab/ci/env_windows_vs2022_x64_ninja_multi.ps1 +++ b/.gitlab/ci/env_windows_vs2022_x64_ninja_multi.ps1 @@ -1,9 +1,9 @@ if ("$env:CMAKE_CI_NIGHTLY" -eq "true") { - Invoke-Expression -Command ".gitlab/ci/ispc-env.ps1" + . ".gitlab/ci/ispc-env.ps1" } $pwdpath = $pwd.Path -powershell -File ".gitlab/ci/ninja.ps1" +& "$pwsh" -File ".gitlab/ci/ninja.ps1" Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab;$env:PATH" ninja --version diff --git a/.gitlab/ci/extdeps-linux.sh b/.gitlab/ci/extdeps-linux.sh new file mode 100755 index 0000000..f0d4c0d --- /dev/null +++ b/.gitlab/ci/extdeps-linux.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +set -e + +mkdir -p /opt/extdeps/src +cd /opt/extdeps/src +export PATH=/opt/extdeps/bin:$PATH + +#---------------------------------------------------------------------------- +# cmake + +case "$(uname -s)-$(uname -m)" in + Linux-x86_64) + cmake_version="3.13.5" + cmake_sha256sum="e2fd0080a6f0fc1ec84647acdcd8e0b4019770f48d83509e6a5b0b6ea27e5864" + cmake_platform="Linux-x86_64" + ;; + Linux-aarch64) + cmake_version="3.19.8" + cmake_sha256sum="807f5afb2a560e00af9640e496d5673afefc2888bf0ed076412884a5ebb547a1" + cmake_platform="Linux-aarch64" + ;; + *) + echo "Unrecognized platform $(uname -s)-$(uname -m)" + exit 1 + ;; +esac +readonly shatool +readonly cmake_sha256sum +readonly cmake_platform + +readonly cmake_filename="cmake-$cmake_version-$cmake_platform" +readonly cmake_tarball="$cmake_filename.tar.gz" + +echo "$cmake_sha256sum $cmake_tarball" > cmake.sha256sum +curl -OL "https://github.com/Kitware/CMake/releases/download/v$cmake_version/$cmake_tarball" +sha256sum --check cmake.sha256sum +tar xzf "$cmake_tarball" -C /opt/extdeps --strip-components=1 +rm -f "$cmake_tarball" cmake.sha256sum + +#---------------------------------------------------------------------------- +# libuv + +curl -L -o libuv-1.28.0.tar.gz https://github.com/libuv/libuv/archive/refs/tags/v1.28.0.tar.gz +tar xzf libuv-1.28.0.tar.gz +cmake -S libuv-1.28.0 -B libuv-1.28.0-build \ + -DCMAKE_INSTALL_PREFIX=/opt/extdeps +cmake --build libuv-1.28.0-build --target install +rm -rf libuv-1.28.0* + +#---------------------------------------------------------------------------- +# jsoncpp + +curl -L -o jsoncpp-1.6.0.tar.gz https://github.com/open-source-parsers/jsoncpp/archive/refs/tags/1.6.0.tar.gz +tar xzf jsoncpp-1.6.0.tar.gz +cmake -S jsoncpp-1.6.0 -B jsoncpp-1.6.0-build \ + -DCMAKE_BUILD_TYPE=Release \ + -DJSONCPP_LIB_BUILD_STATIC=ON \ + -DJSONCPP_LIB_BUILD_SHARED=ON \ + -DCMAKE_INSTALL_PREFIX=/opt/extdeps +cmake --build jsoncpp-1.6.0-build --target install +rm -rf jsoncpp-1.6.0* diff --git a/.gitlab/ci/ispc-env.ps1 b/.gitlab/ci/ispc-env.ps1 index 1baea31..816c485 100755 --- a/.gitlab/ci/ispc-env.ps1 +++ b/.gitlab/ci/ispc-env.ps1 @@ -1,4 +1,4 @@ $pwdpath = $pwd.Path -powershell -File ".gitlab/ci/ispc.ps1" +& "$pwsh" -File ".gitlab/ci/ispc.ps1" Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab\ispc\bin;$env:PATH" ispc --version diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 12fbc1e..84950d2 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -45,7 +45,7 @@ ### Debian .debian10: - image: "kitware/cmake:ci-debian10-x86_64-2022-06-21" + image: "kitware/cmake:ci-debian10-x86_64-2022-08-30" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" @@ -60,7 +60,7 @@ CMAKE_CI_NO_INSTALL: 1 .debian10_aarch64: - image: "kitware/cmake:ci-debian10-aarch64-2022-06-21" + image: "kitware/cmake:ci-debian10-aarch64-2022-08-30" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" @@ -69,7 +69,7 @@ ### Fedora .fedora36: - image: "kitware/cmake:ci-fedora36-x86_64-2022-06-21" + image: "kitware/cmake:ci-fedora36-x86_64-2022-10-04" variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci/long file name for testing purposes" @@ -137,6 +137,30 @@ CMAKE_CI_NO_INSTALL: 1 CTEST_NO_WARNINGS_ALLOWED: 1 +.debian10_extdeps: + extends: .debian10 + + variables: + CMAKE_CONFIGURATION: debian10_extdeps + CMAKE_CI_BUILD_TYPE: Release + CTEST_NO_WARNINGS_ALLOWED: 1 + +.debian10_aarch64_extdeps: + extends: .debian10_aarch64 + + variables: + CMAKE_CONFIGURATION: debian10_aarch64_extdeps + CMAKE_CI_BUILD_TYPE: Release + CTEST_NO_WARNINGS_ALLOWED: 1 + +.fedora36_extdeps: + extends: .fedora36 + + variables: + CMAKE_CONFIGURATION: fedora36_extdeps + CMAKE_CI_BUILD_TYPE: Release + CTEST_NO_WARNINGS_ALLOWED: 1 + .fedora36_ninja: extends: .fedora36 @@ -299,6 +323,30 @@ CMAKE_CONFIGURATION: hip4.2_radeon CMAKE_GENERATOR: "Ninja Multi-Config" +### C++ modules + +.gcc_cxx_modules_x86_64: + image: "kitware/cmake:ci-gcc_cxx_modules-x86_64-2022-06-21" + + variables: + GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" + CMAKE_ARCH: x86_64 + CC: "/opt/gcc-p1689/bin/gcc" + CXX: "/opt/gcc-p1689/bin/g++" + +.gcc_cxx_modules_ninja: + extends: .gcc_cxx_modules_x86_64 + + variables: + CMAKE_CONFIGURATION: linux_gcc_cxx_modules_ninja + +.gcc_cxx_modules_ninja_multi: + extends: .gcc_cxx_modules_x86_64 + + variables: + CMAKE_CONFIGURATION: linux_gcc_cxx_modules_ninja_multi + CMAKE_GENERATOR: "Ninja Multi-Config" + ## Tags .linux_builder_tags: @@ -457,7 +505,7 @@ # use the scripts here. - "$LAUNCHER make -j$(nproc)" # NOTE: This regex matches that used in the release build. - - "$LAUNCHER bin/ctest --output-on-failure -j$(nproc) -R '^(CMake\\.|CMakeLib\\.|CMakeServerLib\\.|RunCMake\\.ctest_memcheck)'" + - "$LAUNCHER bin/ctest --output-on-failure -j$(nproc) -R '^(CMake\\.|CMakeLib\\.|RunCMake\\.ctest_memcheck)'" # Make a package. - bin/cpack -G TGZ - bin/cpack -G STGZ diff --git a/.gitlab/os-windows.yml b/.gitlab/os-windows.yml index 282cf1e..5c6be11 100644 --- a/.gitlab/os-windows.yml +++ b/.gitlab/os-windows.yml @@ -293,13 +293,13 @@ ## Windows-specific scripts .before_script_windows: &before_script_windows - - Invoke-Expression -Command .gitlab/ci/env.ps1 + - . .gitlab/ci/env.ps1 - $pwdpath = $pwd.Path - - powershell -File ".gitlab/ci/wix.ps1" + - (& "$pwsh" -File ".gitlab/ci/wix.ps1") - Set-Item -Force -Path "env:WIX" -Value "$pwdpath\.gitlab\wix" - - powershell -File ".gitlab/ci/cmake.ps1" + - (& "$pwsh" -File ".gitlab/ci/cmake.ps1") - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab\cmake\bin;$env:PATH" - - powershell -File ".gitlab/ci/ninja.ps1" + - (& "$pwsh" -File ".gitlab/ci/ninja.ps1") - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab;$env:PATH" - (& "$env:WIX\bin\light.exe" -help) | Select -First 1 - cmake --version @@ -352,7 +352,7 @@ stage: test-ext script: - - Invoke-Expression -Command .gitlab/ci/env.ps1 + - . .gitlab/ci/env.ps1 - build/install/bin/ctest --output-on-failure -V -S .gitlab/ci/ctest_standalone.cmake interruptible: true @@ -361,6 +361,7 @@ stage: test-ext script: + - . .gitlab/ci/env.ps1 - Invoke-Expression -Command .gitlab/ci/vcvarsall.ps1 - build/install/bin/ctest --output-on-failure -V -S .gitlab/ci/ctest_standalone.cmake @@ -370,6 +371,7 @@ stage: test-ext script: + - . .gitlab/ci/env.ps1 - Invoke-Expression -Command .gitlab/ci/jom.ps1 - $pwdpath = $pwd.Path - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab\jom;$env:PATH" @@ -382,6 +384,7 @@ stage: test-ext script: + - . .gitlab/ci/env.ps1 - Invoke-Expression -Command .gitlab/ci/borland.ps1 - $pwdpath = $pwd.Path - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab\bcc\bin;$env:PATH" @@ -393,8 +396,9 @@ stage: test-ext script: + - . .gitlab/ci/env.ps1 - $pwdpath = $pwd.Path - - powershell -File ".gitlab/ci/ninja.ps1" + - (& "$pwsh" -File ".gitlab/ci/ninja.ps1") - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab;$env:PATH" - Invoke-Expression -Command .gitlab/ci/clang.ps1 - Invoke-Expression -Command .gitlab/ci/vcvarsall.ps1 @@ -407,6 +411,7 @@ stage: test-ext script: + - . .gitlab/ci/env.ps1 - Invoke-Expression -Command .gitlab/ci/msvc.ps1 - Invoke-Expression -Command .gitlab/ci/vcvarsall.ps1 - build/install/bin/ctest --output-on-failure -V -S .gitlab/ci/ctest_standalone.cmake @@ -417,6 +422,7 @@ stage: test-ext script: + - . .gitlab/ci/env.ps1 - Invoke-Expression -Command .gitlab/ci/openwatcom.ps1 - $pwdpath = $pwd.Path - Set-Item -Force -Path "env:PATH" -Value "$pwdpath\.gitlab\watcom\binnt;$pwdpath\.gitlab\watcom\binw;$env:PATH" diff --git a/Auxiliary/cmake-mode.el b/Auxiliary/cmake-mode.el index 8224d9e..a11becb 100644 --- a/Auxiliary/cmake-mode.el +++ b/Auxiliary/cmake-mode.el @@ -41,8 +41,8 @@ set the path with these commands: :group 'cmake) ;; Keywords -(defconst cmake-keywords-block-open '("IF" "MACRO" "FOREACH" "ELSE" "ELSEIF" "WHILE" "FUNCTION")) -(defconst cmake-keywords-block-close '("ENDIF" "ENDFOREACH" "ENDMACRO" "ELSE" "ELSEIF" "ENDWHILE" "ENDFUNCTION")) +(defconst cmake-keywords-block-open '("BLOCK" "IF" "MACRO" "FOREACH" "ELSE" "ELSEIF" "WHILE" "FUNCTION")) +(defconst cmake-keywords-block-close '("ENDBLOCK" "ENDIF" "ENDFOREACH" "ENDMACRO" "ELSE" "ELSEIF" "ENDWHILE" "ENDFUNCTION")) (defconst cmake-keywords (let ((kwds (append cmake-keywords-block-open cmake-keywords-block-close nil))) (delete-dups kwds))) @@ -288,6 +288,39 @@ This puts the mark at the end, and point at the beginning." ;------------------------------------------------------------------------------ +(defun cmake--syntax-propertize-until-bracket-close (syntax) + ;; This function assumes that a previous search has matched the + ;; beginning of a bracket_comment or bracket_argument and that the + ;; second capture group has matched the equal signs between the two + ;; opening brackets + (let* ((mb (match-beginning 2)) + (me (match-end 2)) + (cb (format "]%s]" (buffer-substring mb me)))) + (save-match-data + (if (search-forward cb end 'move) + (progn + (setq me (match-end 0)) + (put-text-property + (1- me) + me + 'syntax-table + (string-to-syntax syntax))) + (setq me end))) + (put-text-property + (match-beginning 1) + me + 'syntax-multiline + t))) + +(defconst cmake--syntax-propertize-function + (syntax-propertize-rules + ("\\(#\\)\\[\\(=*\\)\\[" + (1 + (prog1 "!" (cmake--syntax-propertize-until-bracket-close "!")))) + ("\\(\\[\\)\\(=*\\)\\[" + (1 + (prog1 "|" (cmake--syntax-propertize-until-bracket-close "|")))))) + ;; Syntax table for this mode. (defvar cmake-mode-syntax-table nil "Syntax table for CMake mode.") @@ -318,7 +351,10 @@ This puts the mark at the end, and point at the beginning." ; Setup indentation function. (set (make-local-variable 'indent-line-function) 'cmake-indent) ; Setup comment syntax. - (set (make-local-variable 'comment-start) "#")) + (set (make-local-variable 'comment-start) "#") + ;; Setup syntax propertization + (set (make-local-variable 'syntax-propertize-function) cmake--syntax-propertize-function) + (add-hook 'syntax-propertize-extend-region-functions #'syntax-propertize-multiline nil t)) ;; Default cmake-mode key bindings (define-key cmake-mode-map "\e\C-a" #'cmake-beginning-of-defun) diff --git a/Auxiliary/vim/indent/cmake.vim b/Auxiliary/vim/indent/cmake.vim index 672bdcc..0c662fa 100644 --- a/Auxiliary/vim/indent/cmake.vim +++ b/Auxiliary/vim/indent/cmake.vim @@ -59,8 +59,8 @@ fun! CMakeGetIndent(lnum) let cmake_closing_parens_line = '^\s*\()\+\)\s*$' - let cmake_indent_begin_regex = '^\s*\(IF\|MACRO\|FOREACH\|ELSE\|ELSEIF\|WHILE\|FUNCTION\)\s*(' - let cmake_indent_end_regex = '^\s*\(ENDIF\|ENDFOREACH\|ENDMACRO\|ELSE\|ELSEIF\|ENDWHILE\|ENDFUNCTION\)\s*(' + let cmake_indent_begin_regex = '^\s*\(BLOCK\|IF\|MACRO\|FOREACH\|ELSE\|ELSEIF\|WHILE\|FUNCTION\)\s*(' + let cmake_indent_end_regex = '^\s*\(ENDBLOCK\|ENDIF\|ENDFOREACH\|ENDMACRO\|ELSE\|ELSEIF\|ENDWHILE\|ENDFUNCTION\)\s*(' if this_line =~? cmake_closing_parens_line if previous_line !~? cmake_indent_open_regex diff --git a/Auxiliary/vim/syntax/cmake.vim b/Auxiliary/vim/syntax/cmake.vim index e1a2885..9eb993a 100644 --- a/Auxiliary/vim/syntax/cmake.vim +++ b/Auxiliary/vim/syntax/cmake.vim @@ -436,6 +436,7 @@ syn keyword cmakeProperty contained \ XCODE_SCHEME_ENVIRONMENT \ XCODE_SCHEME_EXECUTABLE \ XCODE_SCHEME_GUARD_MALLOC + \ XCODE_SCHEME_LAUNCH_MODE \ XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP \ XCODE_SCHEME_MALLOC_GUARD_EDGES \ XCODE_SCHEME_MALLOC_SCRIBBLE @@ -444,6 +445,9 @@ syn keyword cmakeProperty contained \ XCODE_SCHEME_THREAD_SANITIZER_STOP \ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER \ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP + \ XCODE_SCHEME_ENABLE_GPU_API_VALIDATION + \ XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION + \ XCODE_SCHEME_LAUNCH_CONFIGURATION \ XCODE_SCHEME_WORKING_DIRECTORY \ XCODE_SCHEME_ZOMBIE_OBJECTS \ XCTEST @@ -1537,6 +1541,7 @@ syn keyword cmakeVariable contained \ CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE \ CMAKE_XCODE_SCHEME_ENVIRONMENT \ CMAKE_XCODE_SCHEME_GUARD_MALLOC + \ CMAKE_XCODE_SCHEME_LAUNCH_MODE \ CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP \ CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES \ CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE @@ -1545,6 +1550,9 @@ syn keyword cmakeVariable contained \ CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP \ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER \ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP + \ CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION + \ CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION + \ CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION \ CMAKE_XCODE_SCHEME_WORKING_DIRECTORY \ CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS \ CPACK_ABSOLUTE_DESTINATION_FILES @@ -3830,6 +3838,7 @@ syn keyword cmakeCommand \ add_subdirectory \ add_test \ aux_source_directory + \ block \ break \ build_command \ cmake_host_system_information @@ -3857,6 +3866,7 @@ syn keyword cmakeCommand \ define_property \ enable_language \ enable_testing + \ endblock \ endfunction \ endmacro \ execute_process diff --git a/CMakeLists.txt b/CMakeLists.txt index 9de5338..2b9eb2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -cmake_minimum_required(VERSION 3.13...3.22 FATAL_ERROR) +cmake_minimum_required(VERSION 3.13...3.23 FATAL_ERROR) set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideC.cmake) set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/Source/Modules/OverrideCXX.cmake) @@ -17,8 +17,8 @@ unset(CMAKE_USER_MAKE_RULES_OVERRIDE_C) if(MSVC AND NOT CMAKE_VERSION VERSION_LESS 3.15) # Filter out MSVC runtime library flags that may have come from # the cache of an existing build tree or from scripts. - foreach(l C CXX) - foreach(c DEBUG MINSIZEREL RELEASE RELWITHDEBINFO) + foreach(l IN ITEMS C CXX) + foreach(c IN ITEMS DEBUG MINSIZEREL RELEASE RELWITHDEBINFO) string(REGEX REPLACE "[-/]M[DT]d?( |$)" "" "CMAKE_${l}_FLAGS_${c}" "${CMAKE_${l}_FLAGS_${c}}") endforeach() endforeach() @@ -60,17 +60,6 @@ else() set(USE_LGPL "") endif() -if("${CMake_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") - # Disallow architecture-specific try_run. It may not run on the host. - macro(TRY_RUN) - if(CMAKE_TRY_COMPILE_OSX_ARCHITECTURES) - message(FATAL_ERROR "TRY_RUN not allowed with CMAKE_TRY_COMPILE_OSX_ARCHITECTURES=[${CMAKE_TRY_COMPILE_OSX_ARCHITECTURES}]") - else() - _TRY_RUN(${ARGV}) - endif() - endmacro() -endif() - # Use most-recent available language dialects with GNU and Clang if(NOT DEFINED CMAKE_C_STANDARD AND NOT CMake_NO_C_STANDARD) include(${CMake_SOURCE_DIR}/Source/Checks/cm_c11_thread_local.cmake) @@ -81,7 +70,7 @@ if(NOT DEFINED CMAKE_C_STANDARD AND NOT CMake_NO_C_STANDARD) endif() endif() if(NOT DEFINED CMAKE_CXX_STANDARD AND NOT CMake_NO_CXX_STANDARD) - if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.14) + if(CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.14) set(CMAKE_CXX_STANDARD 98) else() if(NOT CMAKE_VERSION VERSION_LESS 3.8) @@ -114,9 +103,7 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) endif() # Inform STL library header wrappers whether to use system versions. -configure_file(${CMake_SOURCE_DIR}/Utilities/std/cmSTL.hxx.in - ${CMake_BINARY_DIR}/Utilities/cmSTL.hxx - @ONLY) +configure_file(Utilities/std/cmSTL.hxx.in Utilities/cmSTL.hxx @ONLY) # set the internal encoding of CMake to UTF-8 set(KWSYS_ENCODING_DEFAULT_CODEPAGE CP_UTF8) @@ -143,7 +130,7 @@ option(CMake_BUILD_DEVELOPER_REFERENCE mark_as_advanced(CMake_BUILD_DEVELOPER_REFERENCE) # option to build using interprocedural optimizations (IPO/LTO) -if (NOT CMAKE_VERSION VERSION_LESS 3.12.2) +if(NOT CMAKE_VERSION VERSION_LESS 3.12.2) option(CMake_BUILD_LTO "Compile CMake with link-time optimization if supported" OFF) if(CMake_BUILD_LTO) include(CheckIPOSupported) @@ -165,7 +152,7 @@ macro(CMAKE_HANDLE_SYSTEM_LIBRARIES) # Allow the user to enable/disable all system utility library options by # defining CMAKE_USE_SYSTEM_LIBRARIES or CMAKE_USE_SYSTEM_LIBRARY_${util}. set(UTILITIES BZIP2 CURL EXPAT FORM JSONCPP LIBARCHIVE LIBLZMA LIBRHASH LIBUV NGHTTP2 ZLIB ZSTD) - foreach(util ${UTILITIES}) + foreach(util IN LISTS UTILITIES) if(NOT DEFINED CMAKE_USE_SYSTEM_LIBRARY_${util} AND DEFINED CMAKE_USE_SYSTEM_LIBRARIES) set(CMAKE_USE_SYSTEM_LIBRARY_${util} "${CMAKE_USE_SYSTEM_LIBRARIES}") @@ -215,16 +202,14 @@ macro(CMAKE_HANDLE_SYSTEM_LIBRARIES) mark_as_advanced(CMAKE_USE_SYSTEM_KWIML) # Mention to the user what system libraries are being used. - foreach(util ${UTILITIES} KWIML) + foreach(util IN LISTS UTILITIES ITEMS KWIML) if(CMAKE_USE_SYSTEM_${util}) message(STATUS "Using system-installed ${util}") endif() endforeach() # Inform utility library header wrappers whether to use system versions. - configure_file(${CMake_SOURCE_DIR}/Utilities/cmThirdParty.h.in - ${CMake_BINARY_DIR}/Utilities/cmThirdParty.h - @ONLY) + configure_file(Utilities/cmThirdParty.h.in Utilities/cmThirdParty.h @ONLY) endmacro() @@ -235,7 +220,7 @@ endmacro() macro(CMAKE_SETUP_TESTING) if(BUILD_TESTING) set(CMAKE_TEST_SYSTEM_LIBRARIES 0) - foreach(util CURL EXPAT ZLIB) + foreach(util IN ITEMS CURL EXPAT ZLIB) if(CMAKE_USE_SYSTEM_${util}) set(CMAKE_TEST_SYSTEM_LIBRARIES 1) endif() @@ -250,7 +235,7 @@ macro(CMAKE_SETUP_TESTING) set(CMAKE_CTEST_COMMAND "${CMake_TEST_EXTERNAL_CMAKE}/ctest") set(CMAKE_CMAKE_COMMAND "${CMake_TEST_EXTERNAL_CMAKE}/cmake") set(CMAKE_CPACK_COMMAND "${CMake_TEST_EXTERNAL_CMAKE}/cpack") - foreach(exe cmake ctest cpack) + foreach(exe IN ITEMS cmake ctest cpack) add_executable(${exe} IMPORTED) set_property(TARGET ${exe} PROPERTY IMPORTED_LOCATION ${CMake_TEST_EXTERNAL_CMAKE}/${exe}) endforeach() @@ -262,18 +247,12 @@ macro(CMAKE_SETUP_TESTING) endif() # configure some files for testing - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Templates/CTestScript.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/CTestScript.cmake" - @ONLY) - configure_file(${CMake_SOURCE_DIR}/Tests/.NoDartCoverage - ${CMake_BINARY_DIR}/Tests/.NoDartCoverage) - configure_file(${CMake_SOURCE_DIR}/Tests/.NoDartCoverage - ${CMake_BINARY_DIR}/Modules/.NoDartCoverage) - configure_file(${CMake_SOURCE_DIR}/CTestCustom.cmake.in - ${CMake_BINARY_DIR}/CTestCustom.cmake @ONLY) + configure_file(Templates/CTestScript.cmake.in CTestScript.cmake @ONLY) + configure_file(Tests/.NoDartCoverage Tests/.NoDartCoverage) + configure_file(Tests/.NoDartCoverage Modules/.NoDartCoverage) + configure_file(CTestCustom.cmake.in CTestCustom.cmake @ONLY) if(BUILD_TESTING AND DART_ROOT) - configure_file(${CMake_SOURCE_DIR}/CMakeLogo.gif - ${CMake_BINARY_DIR}/Testing/HTML/TestingResults/Icons/Logo.gif COPYONLY) + configure_file(CMakeLogo.gif Testing/HTML/TestingResults/Icons/Logo.gif COPYONLY) endif() mark_as_advanced(DART_ROOT) endmacro() @@ -339,390 +318,6 @@ macro(CMAKE_SET_TARGET_FOLDER tgt folder) endif() endmacro() - -#----------------------------------------------------------------------- -# a macro to build the utilities used by CMake -# Simply to improve readability of the main script. -#----------------------------------------------------------------------- -macro (CMAKE_BUILD_UTILITIES) - find_package(Threads) - - # Suppress unnecessary checks in third-party code. - include(Utilities/cmThirdPartyChecks.cmake) - - #--------------------------------------------------------------------- - # Create the kwsys library for CMake. - set(KWSYS_NAMESPACE cmsys) - set(KWSYS_USE_SystemTools 1) - set(KWSYS_USE_Directory 1) - set(KWSYS_USE_RegularExpression 1) - set(KWSYS_USE_Base64 1) - set(KWSYS_USE_MD5 1) - set(KWSYS_USE_Process 1) - set(KWSYS_USE_CommandLineArguments 1) - set(KWSYS_USE_ConsoleBuf 1) - set(KWSYS_HEADER_ROOT ${CMake_BINARY_DIR}/Source) - set(KWSYS_INSTALL_DOC_DIR "${CMAKE_DOC_DIR}") - if(CMake_NO_CXX_STANDARD) - set(KWSYS_CXX_STANDARD "") - endif() - if(CMake_NO_SELF_BACKTRACE) - set(KWSYS_NO_EXECINFO 1) - endif() - if(WIN32) - # FIXME: Teach KWSys to hard-code these checks on Windows. - set(KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC_COMPILED 0) - set(KWSYS_C_HAS_PTRDIFF_T_COMPILED 1) - set(KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H_COMPILED 1) - set(KWSYS_CXX_HAS_RLIMIT64_COMPILED 0) - set(KWSYS_CXX_HAS_SETENV_COMPILED 0) - set(KWSYS_CXX_HAS_UNSETENV_COMPILED 0) - set(KWSYS_CXX_HAS_UTIMENSAT_COMPILED 0) - set(KWSYS_CXX_HAS_UTIMES_COMPILED 0) - set(KWSYS_CXX_STAT_HAS_ST_MTIM_COMPILED 0) - set(KWSYS_CXX_STAT_HAS_ST_MTIMESPEC_COMPILED 0) - set(KWSYS_STL_HAS_WSTRING_COMPILED 1) - set(KWSYS_SYS_HAS_IFADDRS_H 0) - endif() - add_subdirectory(Source/kwsys) - set(kwsys_folder "Utilities/KWSys") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE} "${kwsys_folder}") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}_c "${kwsys_folder}") - if(BUILD_TESTING) - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestDynload "${kwsys_folder}") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestProcess "${kwsys_folder}") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestsC "${kwsys_folder}") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestsCxx "${kwsys_folder}") - CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestSharedForward "${kwsys_folder}") - endif() - - #--------------------------------------------------------------------- - # Setup third-party libraries. - # Everything in the tree should be able to include files from the - # Utilities directory. - if ((CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400") AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # using -isystem option generate error "template with C linkage" - include_directories("${CMake_SOURCE_DIR}/Utilities/std") - else() - include_directories(SYSTEM "${CMake_SOURCE_DIR}/Utilities/std") - endif() - - include_directories("${CMake_BINARY_DIR}/Utilities") - if ((CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400") AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # using -isystem option generate error "template with C linkage" - include_directories("${CMake_SOURCE_DIR}/Utilities") - else() - include_directories(SYSTEM "${CMake_SOURCE_DIR}/Utilities") - endif() - - #--------------------------------------------------------------------- - # Build CMake std library for CMake and CTest. - set(CMAKE_STD_LIBRARY cmstd) - add_subdirectory(Utilities/std) - CMAKE_SET_TARGET_FOLDER(cmstd "Utilities/std") - - # check for the use of system libraries versus builtin ones - # (a macro defined in this file) - CMAKE_HANDLE_SYSTEM_LIBRARIES() - - if(CMAKE_USE_SYSTEM_KWIML) - find_package(KWIML 1.0) - if(NOT KWIML_FOUND) - message(FATAL_ERROR "CMAKE_USE_SYSTEM_KWIML is ON but KWIML is not found!") - endif() - set(CMake_KWIML_LIBRARIES kwiml::kwiml) - else() - set(CMake_KWIML_LIBRARIES "") - if(BUILD_TESTING) - set(KWIML_TEST_ENABLE 1) - endif() - add_subdirectory(Utilities/KWIML) - endif() - - if(CMAKE_USE_SYSTEM_LIBRHASH) - find_package(LibRHash) - if(NOT LibRHash_FOUND) - message(FATAL_ERROR - "CMAKE_USE_SYSTEM_LIBRHASH is ON but LibRHash is not found!") - endif() - set(CMAKE_LIBRHASH_LIBRARIES LibRHash::LibRHash) - else() - set(CMAKE_LIBRHASH_LIBRARIES cmlibrhash) - add_subdirectory(Utilities/cmlibrhash) - CMAKE_SET_TARGET_FOLDER(cmlibrhash "Utilities/3rdParty") - endif() - - #--------------------------------------------------------------------- - # Build zlib library for Curl, CMake, and CTest. - set(CMAKE_ZLIB_HEADER "cm_zlib.h") - if(CMAKE_USE_SYSTEM_ZLIB) - find_package(ZLIB) - if(NOT ZLIB_FOUND) - message(FATAL_ERROR - "CMAKE_USE_SYSTEM_ZLIB is ON but a zlib is not found!") - endif() - set(CMAKE_ZLIB_INCLUDES ${ZLIB_INCLUDE_DIR}) - set(CMAKE_ZLIB_LIBRARIES ${ZLIB_LIBRARIES}) - else() - set(CMAKE_ZLIB_INCLUDES ${CMake_SOURCE_DIR}/Utilities) - set(CMAKE_ZLIB_LIBRARIES cmzlib) - set(WITHOUT_ZLIB_DLL "") - set(WITHOUT_ZLIB_DLL_WITH_LIB cmzlib) - set(ZLIB_DLL "") - set(ZLIB_DLL_WITH_LIB cmzlib) - set(ZLIB_WINAPI "") - set(ZLIB_WINAPI_COMPILED 0) - set(ZLIB_WINAPI_WITH_LIB cmzlib) - add_subdirectory(Utilities/cmzlib) - CMAKE_SET_TARGET_FOLDER(cmzlib "Utilities/3rdParty") - endif() - - #--------------------------------------------------------------------- - # Build Curl library for CTest. - if(CMAKE_USE_SYSTEM_CURL) - find_package(CURL) - if(NOT CURL_FOUND) - message(FATAL_ERROR - "CMAKE_USE_SYSTEM_CURL is ON but a curl is not found!") - endif() - set(CMAKE_CURL_INCLUDES ${CURL_INCLUDE_DIRS}) - set(CMAKE_CURL_LIBRARIES ${CURL_LIBRARIES}) - else() - set(CURL_SPECIAL_ZLIB_H ${CMAKE_ZLIB_HEADER}) - set(CURL_SPECIAL_LIBZ_INCLUDES ${CMAKE_ZLIB_INCLUDES}) - set(CURL_SPECIAL_LIBZ ${CMAKE_ZLIB_LIBRARIES}) - set(CMAKE_CURL_INCLUDES) - set(CMAKE_CURL_LIBRARIES cmcurl) - if(CMAKE_TESTS_CDASH_SERVER) - set(CMAKE_CURL_TEST_URL "${CMAKE_TESTS_CDASH_SERVER}/user.php") - endif() - set(_CMAKE_USE_OPENSSL_DEFAULT OFF) - if(NOT DEFINED CMAKE_USE_OPENSSL AND NOT WIN32 AND NOT APPLE - AND CMAKE_SYSTEM_NAME MATCHES "(Linux|FreeBSD)") - set(_CMAKE_USE_OPENSSL_DEFAULT ON) - endif() - option(CMAKE_USE_OPENSSL "Use OpenSSL." ${_CMAKE_USE_OPENSSL_DEFAULT}) - mark_as_advanced(CMAKE_USE_OPENSSL) - if(CMAKE_USE_OPENSSL) - set(CURL_CA_BUNDLE "" CACHE FILEPATH "Path to SSL CA Certificate Bundle") - set(CURL_CA_PATH "" CACHE PATH "Path to SSL CA Certificate Directory") - mark_as_advanced(CURL_CA_BUNDLE CURL_CA_PATH) - endif() - if(NOT CMAKE_USE_SYSTEM_NGHTTP2) - # Tell curl's FindNGHTTP2 module to use our library. - set(NGHTTP2_LIBRARY cmnghttp2) - set(NGHTTP2_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmnghttp2/lib/includes) - endif() - add_subdirectory(Utilities/cmcurl) - CMAKE_SET_TARGET_FOLDER(cmcurl "Utilities/3rdParty") - CMAKE_SET_TARGET_FOLDER(LIBCURL "Utilities/3rdParty") - if(NOT CMAKE_USE_SYSTEM_NGHTTP2) - # Configure after curl to re-use some check results. - add_subdirectory(Utilities/cmnghttp2) - CMAKE_SET_TARGET_FOLDER(cmnghttp2 "Utilities/3rdParty") - endif() - endif() - - #--------------------------------------------------------------------- - # Build expat library for CMake, CTest, and libarchive. - if(CMAKE_USE_SYSTEM_EXPAT) - find_package(EXPAT) - if(NOT EXPAT_FOUND) - message(FATAL_ERROR - "CMAKE_USE_SYSTEM_EXPAT is ON but a expat is not found!") - endif() - set(CMAKE_EXPAT_INCLUDES ${EXPAT_INCLUDE_DIRS}) - set(CMAKE_EXPAT_LIBRARIES ${EXPAT_LIBRARIES}) - else() - set(CMAKE_EXPAT_INCLUDES) - set(CMAKE_EXPAT_LIBRARIES cmexpat) - add_subdirectory(Utilities/cmexpat) - CMAKE_SET_TARGET_FOLDER(cmexpat "Utilities/3rdParty") - endif() - - #--------------------------------------------------------------------- - # Build or use system libbz2 for libarchive. - if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE) - if(CMAKE_USE_SYSTEM_BZIP2) - find_package(BZip2) - else() - set(BZIP2_INCLUDE_DIR - "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmbzip2") - set(BZIP2_LIBRARIES cmbzip2) - set(BZIP2_NEED_PREFIX "") - set(USE_BZIP2_DLL "") - set(USE_BZIP2_DLL_WITH_LIB cmbzip2) - set(USE_BZIP2_STATIC "") - set(USE_BZIP2_STATIC_WITH_LIB cmbzip2) - add_subdirectory(Utilities/cmbzip2) - CMAKE_SET_TARGET_FOLDER(cmbzip2 "Utilities/3rdParty") - endif() - endif() - - #--------------------------------------------------------------------- - # Build or use system zstd for libarchive. - if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE) - if(NOT CMAKE_USE_SYSTEM_ZSTD) - set(ZSTD_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmzstd") - set(ZSTD_LIBRARY cmzstd) - add_subdirectory(Utilities/cmzstd) - CMAKE_SET_TARGET_FOLDER(cmzstd "Utilities/3rdParty") - endif() - endif() - - #--------------------------------------------------------------------- - # Build or use system liblzma for libarchive. - if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE) - if(CMAKE_USE_SYSTEM_LIBLZMA) - find_package(LibLZMA) - if(NOT LIBLZMA_FOUND) - message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!") - endif() - else() - add_subdirectory(Utilities/cmliblzma) - CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty") - set(LIBLZMA_HAS_AUTO_DECODER 1) - set(LIBLZMA_HAS_EASY_ENCODER 1) - set(LIBLZMA_HAS_LZMA_PRESET 1) - set(LIBLZMA_INCLUDE_DIR - "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api") - set(LIBLZMA_LIBRARY cmliblzma) - set(HAVE_LZMA_STREAM_ENCODER_MT 1) - endif() - endif() - - #--------------------------------------------------------------------- - # Build or use system libarchive for CMake and CTest. - if(CMAKE_USE_SYSTEM_LIBARCHIVE) - find_package(LibArchive 3.3.3) - if(NOT LibArchive_FOUND) - message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBARCHIVE is ON but LibArchive is not found!") - endif() - set(CMAKE_TAR_INCLUDES ${LibArchive_INCLUDE_DIRS}) - set(CMAKE_TAR_LIBRARIES ${LibArchive_LIBRARIES}) - else() - set(EXPAT_INCLUDE_DIR ${CMAKE_EXPAT_INCLUDES}) - set(EXPAT_LIBRARY ${CMAKE_EXPAT_LIBRARIES}) - set(ZLIB_INCLUDE_DIR ${CMAKE_ZLIB_INCLUDES}) - set(ZLIB_LIBRARY ${CMAKE_ZLIB_LIBRARIES}) - add_definitions(-DLIBARCHIVE_STATIC) - set(ENABLE_MBEDTLS OFF) - set(ENABLE_NETTLE OFF) - if(DEFINED CMAKE_USE_OPENSSL) - set(ENABLE_OPENSSL "${CMAKE_USE_OPENSSL}") - else() - set(ENABLE_OPENSSL OFF) - endif() - set(ENABLE_LIBB2 OFF) - set(ENABLE_LZ4 OFF) - set(ENABLE_LZO OFF) - set(ENABLE_LZMA ON) - set(ENABLE_ZSTD ON) - set(ENABLE_ZLIB ON) - set(ENABLE_BZip2 ON) - set(ENABLE_LIBXML2 OFF) - set(ENABLE_EXPAT OFF) - set(ENABLE_PCREPOSIX OFF) - set(ENABLE_LibGCC OFF) - set(ENABLE_CNG OFF) - set(ENABLE_TAR OFF) - set(ENABLE_TAR_SHARED OFF) - set(ENABLE_CPIO OFF) - set(ENABLE_CPIO_SHARED OFF) - set(ENABLE_CAT OFF) - set(ENABLE_CAT_SHARED OFF) - set(ENABLE_XATTR OFF) - set(ENABLE_ACL OFF) - set(ENABLE_ICONV OFF) - set(ENABLE_TEST OFF) - set(ENABLE_COVERAGE OFF) - set(ENABLE_INSTALL OFF) - set(POSIX_REGEX_LIB "" CACHE INTERNAL "libarchive: No POSIX regular expression support") - set(ENABLE_SAFESEH "" CACHE INTERNAL "libarchive: No /SAFESEH linker flag") - set(WINDOWS_VERSION "WIN7" CACHE INTERNAL "libarchive: Set Windows version to use (Windows only)") - add_subdirectory(Utilities/cmlibarchive) - CMAKE_SET_TARGET_FOLDER(cmlibarchive "Utilities/3rdParty") - set(CMAKE_TAR_LIBRARIES cmlibarchive ${BZIP2_LIBRARIES}) - endif() - - #--------------------------------------------------------------------- - # Build jsoncpp library. - if(CMAKE_USE_SYSTEM_JSONCPP) - find_package(JsonCpp 1.4.1) - if(NOT JsonCpp_FOUND) - message(FATAL_ERROR - "CMAKE_USE_SYSTEM_JSONCPP is ON but a JsonCpp is not found!") - endif() - if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang") - set_property(TARGET JsonCpp::JsonCpp APPEND PROPERTY - INTERFACE_COMPILE_OPTIONS -Wno-deprecated-declarations) - endif() - set(CMAKE_JSONCPP_LIBRARIES JsonCpp::JsonCpp) - else() - set(CMAKE_JSONCPP_LIBRARIES cmjsoncpp) - add_subdirectory(Utilities/cmjsoncpp) - CMAKE_SET_TARGET_FOLDER(cmjsoncpp "Utilities/3rdParty") - endif() - - #--------------------------------------------------------------------- - # Build libuv library. - if(CMAKE_USE_SYSTEM_LIBUV) - if(WIN32) - find_package(LibUV 1.38.0) - else() - find_package(LibUV 1.28.0) - endif() - if(NOT LIBUV_FOUND) - message(FATAL_ERROR - "CMAKE_USE_SYSTEM_LIBUV is ON but a libuv is not found!") - endif() - set(CMAKE_LIBUV_LIBRARIES LibUV::LibUV) - else() - set(CMAKE_LIBUV_LIBRARIES cmlibuv) - add_subdirectory(Utilities/cmlibuv) - CMAKE_SET_TARGET_FOLDER(cmlibuv "Utilities/3rdParty") - endif() - - #--------------------------------------------------------------------- - # Use curses? - if(NOT DEFINED BUILD_CursesDialog) - if (UNIX) - include(${CMake_SOURCE_DIR}/Source/Checks/Curses.cmake) - set(BUILD_CursesDialog_DEFAULT "${CMakeCheckCurses_COMPILED}") - elseif(WIN32) - set(BUILD_CursesDialog_DEFAULT "OFF") - endif() - option(BUILD_CursesDialog "Build the CMake Curses Dialog ccmake" "${BUILD_CursesDialog_DEFAULT}") - endif () - if(BUILD_CursesDialog) - if(UNIX) - set(CURSES_NEED_NCURSES TRUE) - find_package(Curses) - if(NOT CURSES_FOUND) - message(WARNING - "'ccmake' will not be built because Curses was not found.\n" - "Turn off BUILD_CursesDialog to suppress this message." - ) - set(BUILD_CursesDialog 0) - endif() - elseif(WIN32) - # FIXME: Add support for system-provided pdcurses. - add_subdirectory(Utilities/cmpdcurses) - set(CURSES_LIBRARY cmpdcurses) - set(CURSES_INCLUDE_PATH "") # cmpdcurses has usage requirements - set(CMAKE_USE_SYSTEM_FORM 0) - set(HAVE_CURSES_USE_DEFAULT_COLORS 1) - endif() - endif() - if(BUILD_CursesDialog) - if(NOT CMAKE_USE_SYSTEM_FORM) - add_subdirectory(Source/CursesDialog/form) - elseif(NOT CURSES_FORM_LIBRARY) - message( FATAL_ERROR "CMAKE_USE_SYSTEM_FORM in ON but CURSES_FORM_LIBRARY is not set!" ) - endif() - endif() -endmacro () - #----------------------------------------------------------------------- if(NOT CMake_TEST_EXTERNAL_CMAKE) if(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD") @@ -749,7 +344,7 @@ include(Source/CMakeVersion.cmake) # Include the standard Dart testing module enable_testing() -include (${CMAKE_ROOT}/Modules/Dart.cmake) +include(${CMAKE_ROOT}/Modules/Dart.cmake) # Set up test-time configuration. set_directory_properties(PROPERTIES @@ -803,8 +398,9 @@ if(CMake_TEST_EXTERNAL_CMAKE) endif() if(NOT CMake_TEST_EXTERNAL_CMAKE) - # build the utilities (a macro defined in this file) - CMAKE_BUILD_UTILITIES() + find_package(Threads) + # build the utilities + include(CMakeBuildUtilities) if(BUILD_QtDialog) if(APPLE) @@ -813,10 +409,9 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) set(CMAKE_BUNDLE_LOCATION "${CMAKE_INSTALL_PREFIX}") # make sure CMAKE_INSTALL_PREFIX ends in / if(NOT CMAKE_INSTALL_PREFIX MATCHES "/$") - set(CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/") + string(APPEND CMAKE_INSTALL_PREFIX "/") endif() - set(CMAKE_INSTALL_PREFIX - "${CMAKE_INSTALL_PREFIX}CMake.app/Contents") + string(APPEND CMAKE_INSTALL_PREFIX "CMake.app/Contents") endif() endif() @@ -829,14 +424,11 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) endif() # add the uninstall support - configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - @ONLY) + configure_file(cmake_uninstall.cmake.in cmake_uninstall.cmake @ONLY) add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") - include (CMakeCPack.cmake) + include(CMakeCPack.cmake) endif() @@ -860,10 +452,10 @@ if(NOT CMake_TEST_EXTERNAL_CMAKE) -Wshadow -Wpointer-arith -Wformat-security -Wundef ) - foreach(FLAG_LANG C CXX) - foreach(FLAG ${${FLAG_LANG}_FLAGS_LIST}) + foreach(FLAG_LANG IN ITEMS C CXX) + foreach(FLAG IN LISTS ${FLAG_LANG}_FLAGS_LIST) if(NOT " ${CMAKE_${FLAG_LANG}_FLAGS} " MATCHES " ${FLAG} ") - set(CMAKE_${FLAG_LANG}_FLAGS "${CMAKE_${FLAG_LANG}_FLAGS} ${FLAG}") + string(APPEND CMAKE_${FLAG_LANG}_FLAGS " ${FLAG}") endif() endforeach() endforeach() @@ -883,9 +475,6 @@ add_subdirectory(Tests) if(NOT CMake_TEST_EXTERNAL_CMAKE) if(BUILD_TESTING) CMAKE_SET_TARGET_FOLDER(CMakeLibTests "Tests") - IF(TARGET CMakeServerLibTests) - CMAKE_SET_TARGET_FOLDER(CMakeServerLibTests "Tests") - ENDIF() endif() if(TARGET documentation) CMAKE_SET_TARGET_FOLDER(documentation "Documentation") @@ -894,7 +483,8 @@ endif() if(BUILD_TESTING) add_test(SystemInformationNew "${CMAKE_CMAKE_COMMAND}" - --system-information -G "${CMAKE_GENERATOR}" ) + --system-information -G "${CMAKE_GENERATOR}" + ) endif() if(NOT CMake_TEST_EXTERNAL_CMAKE) diff --git a/CTestCustom.cmake.in b/CTestCustom.cmake.in index 49026a3..85af8ed 100644 --- a/CTestCustom.cmake.in +++ b/CTestCustom.cmake.in @@ -74,6 +74,7 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION "cm(StringCommand|CTestTestHandler)\\.cxx.*warning.*rand.*may return deterministic values" "cm(StringCommand|CTestTestHandler)\\.cxx.*warning.*rand.*isn.*t random" # we do not do crypto "cm(StringCommand|CTestTestHandler)\\.cxx.*warning.*srand.*seed choices are.*poor" # we do not do crypto + "cmFindPackageCommand.cxx.*: warning #177-D: parameter .* was declared but never referenced" "IPA warning: function.*multiply defined in" "LICENSE WARNING" # PGI license expiry. Not useful in nightly testing. @@ -83,6 +84,11 @@ list(APPEND CTEST_CUSTOM_WARNING_EXCEPTION "compilation completed with warnings" # PGI "[0-9]+ Warning\\(s\\) detected" # SunPro + # Ignore false positive on `cm::optional` usage from GCC + "cmGlobalNinjaGenerator.cxx:[0-9]*:[0-9]*: warning: '.*cm::optional<CxxModuleMapFormat>::_mem\\)\\)' may be used uninitialized \\[-Wmaybe-uninitialized\\]" + "cmGlobalNinjaGenerator.cxx:[0-9]*:[0-9]*: note: '.*cm::optional<CxxModuleMapFormat>::_mem\\)\\)' was declared here" + "cmGlobalNinjaGenerator.cxx:[0-9]*:[0-9]*: warning: '\\*\\(\\(void\\*\\)& modmap_fmt \\+4\\)' may be used uninitialized in this function \\[-Wmaybe-uninitialized\\]" + # clang-analyzer exceptions "cmListFileLexer.c:[0-9]+:[0-9]+: warning: Array subscript is undefined" "jsoncpp/src/.*:[0-9]+:[0-9]+: warning: Value stored to .* is never read" diff --git a/CompileFlags.cmake b/CompileFlags.cmake index e6fb20b..bf8a082 100644 --- a/CompileFlags.cmake +++ b/CompileFlags.cmake @@ -18,12 +18,12 @@ endif() # not hurt other versions, and this will work into the # future if(MSVC OR _INTEL_WINDOWS OR _CLANG_MSVC_WINDOWS) - add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) + add_compile_definitions(_CRT_SECURE_NO_DEPRECATE _CRT_NONSTDC_NO_DEPRECATE) else() endif() if(MSVC) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stack:10000000") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_CXX_LINKER_WRAPPER_FLAG}-stack:10000000") endif() # MSVC 14.28 enables C5105, but the Windows SDK 10.0.18362.0 triggers it. @@ -62,7 +62,7 @@ endif() # Use 64-bit off_t on 32-bit Linux if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SIZEOF_VOID_P EQUAL 4) # ensure 64bit offsets are used for filesystem accesses for 32bit compilation - add_definitions(-D_FILE_OFFSET_BITS=64) + add_compile_definitions(_FILE_OFFSET_BITS=64) endif() # Workaround for TOC Overflow on ppc64 @@ -98,7 +98,7 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL SunPro AND endif() endif() -foreach(lang C CXX) +foreach(lang IN ITEMS C CXX) # Suppress warnings from PGI compiler. if (CMAKE_${lang}_COMPILER_ID STREQUAL "PGI") set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -w") @@ -136,3 +136,12 @@ OFF to disable /MP completely." ) endif() endif() endif() + +# Get rid of excess -Wunused-but-set-variable on release builds with LCC >= 1.26 +foreach(l IN ITEMS C CXX) + if(CMAKE_${l}_COMPILER_ID STREQUAL "LCC" AND NOT CMAKE_${l}_COMPILER_VERSION VERSION_LESS 1.26) + foreach(c IN ITEMS MINSIZEREL RELEASE RELWITHDEBINFO) + string(APPEND "CMAKE_${l}_FLAGS_${c}" " -Wno-unused-but-set-variable") + endforeach() + endif() +endforeach() diff --git a/Copyright.txt b/Copyright.txt index 2cf1769..bd45dd1 100644 --- a/Copyright.txt +++ b/Copyright.txt @@ -53,6 +53,7 @@ The following individuals and institutions are among the Contributors: * Clement Creusot <creusot@cs.york.ac.uk> * Daniel Blezek <blezek@gmail.com> * Daniel Pfeifer <daniel@pfeifer-mail.de> +* Dawid Wróbel <me@dawidwrobel.com> * Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> * Eran Ifrah <eran.ifrah@gmail.com> * Esben Mose Hansen, Ange Optimization ApS diff --git a/Help/command/FIND_XXX.txt b/Help/command/FIND_XXX.txt index cd3c78b..59a4e71 100644 --- a/Help/command/FIND_XXX.txt +++ b/Help/command/FIND_XXX.txt @@ -15,6 +15,7 @@ The general signature is: [PATHS [path | ENV var]... ] [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] [PATH_SUFFIXES suffix1 [suffix2 ...]] + [VALIDATOR function] [DOC "cache documentation string"] [NO_CACHE] [REQUIRED] @@ -66,6 +67,26 @@ Options include: Specify additional subdirectories to check below each directory location otherwise considered. +``VALIDATOR`` + .. versionadded:: 3.25 + + Specify a :command:`function` (a :command:`macro` is not an acceptable + choice) which will be called for each found item. The search ends when + the validation function returns a successful status. + + The validation function expects two arguments: output variable name and item + value. By default, the output variable name already holds a ``TRUE`` value. + + .. parsed-literal:: + + function (MY_CHECK output_status item) + if (NOT item MATCHES ...) + set(${output_status} FALSE PARENT_SCOPE) + endif() + endfunction() + + |FIND_XXX| (result NAMES ... VALIDATOR my_check) + ``DOC`` Specify the documentation string for the ``<VAR>`` cache entry. diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 9e60d2d..99adc85 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -67,6 +67,8 @@ The options are: Each byproduct file will be marked with the :prop_sf:`GENERATED` source file property automatically. + *See policy* :policy:`CMP0058` *for the motivation behind this feature.* + Explicit specification of byproducts is supported by the :generator:`Ninja` generator to tell the ``ninja`` build tool how to regenerate byproducts when they are missing. It is @@ -434,7 +436,7 @@ one of the keywords to make clear the behavior they expect. Because generator expressions can be used in custom commands, it is possible to define ``COMMAND`` lines or whole custom commands which evaluate to empty strings for certain configurations. - For **Visual Studio 2010 (and newer)** generators these command + For **Visual Studio 11 2012 (and newer)** generators these command lines or custom commands will be omitted for the specific configuration and no "empty-string-command" will be added. diff --git a/Help/command/add_custom_target.rst b/Help/command/add_custom_target.rst index def23fa..d8882ca 100644 --- a/Help/command/add_custom_target.rst +++ b/Help/command/add_custom_target.rst @@ -42,6 +42,8 @@ The options are: Each byproduct file will be marked with the :prop_sf:`GENERATED` source file property automatically. + *See policy* :policy:`CMP0058` *for the motivation behind this feature.* + Explicit specification of byproducts is supported by the :generator:`Ninja` generator to tell the ``ninja`` build tool how to regenerate byproducts when they are missing. It is diff --git a/Help/command/add_subdirectory.rst b/Help/command/add_subdirectory.rst index 8dba986..13cae10 100644 --- a/Help/command/add_subdirectory.rst +++ b/Help/command/add_subdirectory.rst @@ -5,7 +5,7 @@ Add a subdirectory to the build. .. code-block:: cmake - add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL]) + add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL] [SYSTEM]) Adds a subdirectory to the build. The source_dir specifies the directory in which the source CMakeLists.txt and code files are @@ -33,3 +33,10 @@ dependencies supersede this exclusion. If a target built by the parent project depends on a target in the subdirectory, the dependee target will be included in the parent project build system to satisfy the dependency. + +If the ``SYSTEM`` argument is provided, the :prop_dir:`SYSTEM` directory +property of the subdirectory will be set to true. This property is +used to initialize the :prop_tgt:`SYSTEM` property of each target +created in that subdirectory. The include directories of targets with +:prop_tgt:`SYSTEM` set to true will be treated as ``SYSTEM`` when +compiling consumers. diff --git a/Help/command/block.rst b/Help/command/block.rst new file mode 100644 index 0000000..9d37deb --- /dev/null +++ b/Help/command/block.rst @@ -0,0 +1,75 @@ +block +----- + +.. versionadded:: 3.25 + +Evaluate a group of commands with a dedicated variable and/or policy scope. + +.. code-block:: cmake + + block([SCOPE_FOR (POLICIES|VARIABLES)] [PROPAGATE <var-name>...]) + <commands> + endblock() + +All commands between ``block()`` and the matching :command:`endblock` are +recorded without being invoked. Once the :command:`endblock` is evaluated, the +recorded list of commands is invoked inside the requested scopes, and, finally, +the scopes created by ``block()`` command are removed. + +``SCOPE_FOR`` + Specify which scopes must be created. + + ``POLICIES`` + Create a new policy scope. This is equivalent to + :command:`cmake_policy(PUSH)`. + + ``VARIABLES`` + Create a new variable scope. + + If ``SCOPE_FOR`` is not specified, this is equivalent to: + + .. code-block:: cmake + + block(SCOPE_FOR VARIABLES POLICIES) + +``PROPAGATE`` + When a variable scope is created by :command:`block` command, this option + set or unset the specified variables in the parent scope. This is equivalent + to :command:`set(PARENT_SCOPE)` or :command:`unset(PARENT_SCOPE)` commands. + + .. code-block:: cmake + + set(VAR1 "INIT1") + set(VAR2 "INIT2") + + block(PROPAGATE VAR1 VAR2) + set(VAR1 "VALUE1") + unset(VAR2) + endblock() + + # here, VAR1 holds value VALUE1 and VAR2 is unset + + This option is only allowed when a variable scope is created. An error will + be raised in the other cases. + +When the ``block`` is local to a :command:`foreach` or :command:`while` +command, the commands :command:`break` and :command:`continue` can be used +inside this block. + +.. code-block:: cmake + + while(TRUE) + block() + ... + # the break() command will terminate the while() command + break() + endblock() + endwhile() + + +See Also +^^^^^^^^ + + * :command:`endblock` + * :command:`return` + * :command:`cmake_policy` diff --git a/Help/command/build_command.rst b/Help/command/build_command.rst index a03979d..3d86a2e 100644 --- a/Help/command/build_command.rst +++ b/Help/command/build_command.rst @@ -24,12 +24,12 @@ options, if any. The trailing ``-- -i`` option is added for :ref:`Makefile Generators` if policy :policy:`CMP0061` is not set to ``NEW``. -When invoked, this ``cmake --build`` command line will launch the +When invoked, this :option:`cmake --build` command line will launch the underlying build system tool. .. versionadded:: 3.21 - The ``PARALLEL_LEVEL`` argument can be used to set the ``--parallel`` - flag. + The ``PARALLEL_LEVEL`` argument can be used to set the + :option:`--parallel <cmake--build --parallel>` flag. .. code-block:: cmake @@ -39,7 +39,7 @@ This second signature is deprecated, but still available for backwards compatibility. Use the first signature instead. It sets the given ``<cachevariable>`` to a command-line string as -above but without the ``--target`` option. +above but without the :option:`--target <cmake--build --target>` option. The ``<makecommand>`` is ignored but should be the full path to devenv, nmake, make or one of the end user build tools for legacy invocations. diff --git a/Help/command/cmake_language.rst b/Help/command/cmake_language.rst index cb8d60b..8801a9f 100644 --- a/Help/command/cmake_language.rst +++ b/Help/command/cmake_language.rst @@ -14,6 +14,7 @@ Synopsis cmake_language(`EVAL`_ CODE <code>...) cmake_language(`DEFER`_ <options>... CALL <command> [<arg>...]) cmake_language(`SET_DEPENDENCY_PROVIDER`_ <command> SUPPORTED_METHODS <methods>...) + cmake_language(`GET_MESSAGE_LOG_LEVEL`_ <out-var>) Introduction ^^^^^^^^^^^^ @@ -50,6 +51,7 @@ is equivalent to To ensure consistency of the code, the following commands are not allowed: * ``if`` / ``elseif`` / ``else`` / ``endif`` + * ``block`` / ``endblock`` * ``while`` / ``endwhile`` * ``foreach`` / ``endforeach`` * ``function`` / ``endfunction`` @@ -491,3 +493,29 @@ calling the provider command recursively for the same dependency. SET_DEPENDENCY_PROVIDER mycomp_provide_dependency SUPPORTED_METHODS FIND_PACKAGE ) + +Getting current message log level +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.25 + +.. _GET_MESSAGE_LOG_LEVEL: +.. _query_message_log_level: + +.. code-block:: cmake + + cmake_language(GET_MESSAGE_LOG_LEVEL <output_variable>) + +Writes the current :command:`message` logging level +into the given ``<output_variable>``. + +See :command:`message` for the possible logging levels. + +The current message logging level can be set either using the +:option:`--log-level <cmake --log-level>` +command line option of the :manual:`cmake(1)` program or using +the :variable:`CMAKE_MESSAGE_LOG_LEVEL` variable. + +If both the command line option and the variable are set, the command line +option takes precedence. If neither are set, the default logging level +is returned. diff --git a/Help/command/cmake_policy.rst b/Help/command/cmake_policy.rst index 94060d9..54fc548 100644 --- a/Help/command/cmake_policy.rst +++ b/Help/command/cmake_policy.rst @@ -103,6 +103,47 @@ Calls to the :command:`cmake_minimum_required(VERSION)`, ``cmake_policy(VERSION)``, or ``cmake_policy(SET)`` commands influence only the current top of the policy stack. +.. versionadded:: 3.25 + The :command:`block` and :command:`endblock` commands offer a more flexible + and more secure way to manage the policy stack. The pop action is done + automatically when the :command:`endblock` command is executed, so it avoid + to call the :command:`cmake_policy(POP)` command before each + :command:`return` command. + + .. code-block:: cmake + + # stack management with cmake_policy() + function(my_func) + cmake_policy(PUSH) + cmake_policy(SET ...) + if (<cond1>) + ... + cmake_policy(POP) + return() + elseif(<cond2>) + ... + cmake_policy(POP) + return() + endif() + ... + cmake_policy(POP) + endfunction() + + # stack management with block()/endblock() + function(my_func) + block(SCOPE_FOR POLICIES) + cmake_policy(SET ...) + if (<cond1>) + ... + return() + elseif(<cond2>) + ... + return() + endif() + ... + endblock() + endfunction() + Commands created by the :command:`function` and :command:`macro` commands record policy settings when they are created and use the pre-record policies when they are invoked. If the function or diff --git a/Help/command/ctest_build.rst b/Help/command/ctest_build.rst index e05df1a..8c81f2d 100644 --- a/Help/command/ctest_build.rst +++ b/Help/command/ctest_build.rst @@ -40,8 +40,8 @@ The options are: ``CONFIGURATION <config>`` Specify the build configuration (e.g. ``Debug``). If not specified the ``CTEST_BUILD_CONFIGURATION`` variable will be checked. - Otherwise the ``-C <cfg>`` option given to the :manual:`ctest(1)` - command will be used, if any. + Otherwise the :option:`-C \<cfg\> <ctest -C>` option given to the + :manual:`ctest(1)` command will be used, if any. ``PARALLEL_LEVEL <parallel>`` .. versionadded:: 3.21 @@ -54,7 +54,7 @@ The options are: Pass additional arguments to the underlying build command. If not specified the ``CTEST_BUILD_FLAGS`` variable will be checked. This can, e.g., be used to trigger a parallel build using the - ``-j`` option of make. See the :module:`ProcessorCount` module + ``-j`` option of ``make``. See the :module:`ProcessorCount` module for an example. ``PROJECT_NAME <project-name>`` diff --git a/Help/command/ctest_run_script.rst b/Help/command/ctest_run_script.rst index 5ec543e..a2b348f 100644 --- a/Help/command/ctest_run_script.rst +++ b/Help/command/ctest_run_script.rst @@ -1,15 +1,15 @@ ctest_run_script ---------------- -runs a ctest -S script +runs a :option:`ctest -S` script :: ctest_run_script([NEW_PROCESS] script_file_name script_file_name1 script_file_name2 ... [RETURN_VALUE var]) -Runs a script or scripts much like if it was run from ctest -S. If no -argument is provided then the current script is run using the current +Runs a script or scripts much like if it was run from :option:`ctest -S`. +If no argument is provided then the current script is run using the current settings of the variables. If ``NEW_PROCESS`` is specified then each script will be run in a separate process.If ``RETURN_VALUE`` is specified the return value of the last script run will be put into ``var``. diff --git a/Help/command/ctest_start.rst b/Help/command/ctest_start.rst index c0f3c6d..921279a 100644 --- a/Help/command/ctest_start.rst +++ b/Help/command/ctest_start.rst @@ -45,7 +45,7 @@ The parameters are as follows: ctest_start(Experimental GROUP GroupExperimental) - Later, in another ``ctest -S`` script: + Later, in another :option:`ctest -S` script: .. code-block:: cmake diff --git a/Help/command/ctest_test.rst b/Help/command/ctest_test.rst index 65f82d7..4f9f891 100644 --- a/Help/command/ctest_test.rst +++ b/Help/command/ctest_test.rst @@ -109,8 +109,9 @@ The options are: While running tests in parallel, try not to start tests when they may cause the CPU load to pass above a given threshold. If not specified the :variable:`CTEST_TEST_LOAD` variable will be checked, - and then the ``--test-load`` command-line argument to :manual:`ctest(1)`. - See also the ``TestLoad`` setting in the :ref:`CTest Test Step`. + and then the :option:`--test-load <ctest --test-load>` command-line + argument to :manual:`ctest(1)`. See also the ``TestLoad`` setting + in the :ref:`CTest Test Step`. ``REPEAT <mode>:<n>`` .. versionadded:: 3.17 @@ -176,8 +177,9 @@ See also the :variable:`CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE`, :variable:`CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE` and :variable:`CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION` variables, along with their corresponding :manual:`ctest(1)` command line options -``--test-output-size-passed``, ``--test-output-size-failed``, and -``--test-output-truncation``. +:option:`--test-output-size-passed <ctest --test-output-size-passed>`, +:option:`--test-output-size-failed <ctest --test-output-size-failed>`, and +:option:`--test-output-truncation <ctest --test-output-truncation>`. .. _`Additional Test Measurements`: diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst index d2acbc8..d9103b8 100644 --- a/Help/command/enable_language.rst +++ b/Help/command/enable_language.rst @@ -1,13 +1,14 @@ enable_language --------------- -Enable a language (CXX/C/OBJC/OBJCXX/Fortran/etc) + +Enable languages (CXX/C/OBJC/OBJCXX/Fortran/etc) .. code-block:: cmake - enable_language(<lang> [OPTIONAL] ) + enable_language(<lang>... [OPTIONAL]) -Enables support for the named language in CMake. This is -the same as the :command:`project` command but does not create any of the extra +Enables support for the named languages in CMake. This is the same as +the :command:`project` command but does not create any of the extra variables that are created by the project command. Example languages are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``, ``HIP``, ``ISPC``, and ``ASM``. diff --git a/Help/command/endblock.rst b/Help/command/endblock.rst new file mode 100644 index 0000000..3b21c12 --- /dev/null +++ b/Help/command/endblock.rst @@ -0,0 +1,11 @@ +endblock +-------- + +.. versionadded:: 3.25 + +Ends a list of commands in a :command:`block` and removes the scopes +created by the :command:`block` command. + +.. code-block:: cmake + + endblock() diff --git a/Help/command/export.rst b/Help/command/export.rst index dc69645..0f79f63 100644 --- a/Help/command/export.rst +++ b/Help/command/export.rst @@ -25,7 +25,8 @@ Exporting Targets .. code-block:: cmake export(TARGETS <target>... [NAMESPACE <namespace>] - [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES]) + [APPEND] FILE <filename> [EXPORT_LINK_INTERFACE_LIBRARIES] + [CXX_MODULES_DIRECTORY <directory>]) Creates a file ``<filename>`` that may be included by outside projects to import targets named by ``<target>...`` from the current project's build tree. @@ -52,6 +53,16 @@ The options are: in the export, even when policy :policy:`CMP0022` is NEW. This is useful to support consumers using CMake versions older than 2.8.12. +``CXX_MODULES_DIRECTORY <directory>`` + + .. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + + Export C++ module properties to files under the given directory. Each file + will be named according to the target's export name (without any namespace). + These files will automatically be included from the export file. + This signature requires all targets to be listed explicitly. If a library target is included in the export, but a target to which it links is not included, the behavior is unspecified. See the `export(EXPORT)`_ signature @@ -95,7 +106,8 @@ Exporting Targets matching install(EXPORT) .. code-block:: cmake - export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>]) + export(EXPORT <export-name> [NAMESPACE <namespace>] [FILE <filename>] + [CXX_MODULES_DIRECTORY <directory>]) Creates a file ``<filename>`` that may be included by outside projects to import targets from the current project's build tree. This is the same diff --git a/Help/command/file.rst b/Help/command/file.rst index 3374d2d..fbe2a81 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -1121,8 +1121,11 @@ Additional options to ``DOWNLOAD`` are: Verify that the downloaded content hash matches the expected value, where ``ALGO`` is one of the algorithms supported by ``file(<HASH>)``. - If it does not match, the operation fails with an error. It is an error to - specify this if ``DOWNLOAD`` is not given a ``<file>``. + If the file already exists and matches the hash, the download is skipped. + If the file already exists and does not match the hash, the file is + downloaded again. If after download the file does not match the hash, the + operation fails with an error. It is an error to specify this option if + ``DOWNLOAD`` is not given a ``<file>``. ``EXPECTED_MD5 <value>`` Historical short-hand for ``EXPECTED_HASH MD5=<value>``. It is an error to diff --git a/Help/command/find_package.rst b/Help/command/find_package.rst index c96d84e..c99c73d 100644 --- a/Help/command/find_package.rst +++ b/Help/command/find_package.rst @@ -285,29 +285,40 @@ CMake constructs a set of possible installation prefixes for the package. Under each prefix several directories are searched for a configuration file. The tables below show the directories searched. Each entry is meant for installation trees following Windows (``W``), UNIX -(``U``), or Apple (``A``) conventions:: - - <prefix>/ (W) - <prefix>/(cmake|CMake)/ (W) - <prefix>/<name>*/ (W) - <prefix>/<name>*/(cmake|CMake)/ (W) - <prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/ (U) - <prefix>/(lib/<arch>|lib*|share)/<name>*/ (U) - <prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (U) - <prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/ (W/U) - <prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/ (W/U) - <prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/ (W/U) +(``U``), or Apple (``A``) conventions: + +==================================================================== ========== + Entry Convention +==================================================================== ========== + ``<prefix>/`` W + ``<prefix>/(cmake|CMake)/`` W + ``<prefix>/<name>*/`` W + ``<prefix>/<name>*/(cmake|CMake)/`` W + ``<prefix>/<name>*/(cmake|CMake)/<name>*/`` [#]_ W + ``<prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/`` U + ``<prefix>/(lib/<arch>|lib*|share)/<name>*/`` U + ``<prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/`` U + ``<prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/`` W/U + ``<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/`` W/U + ``<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/`` W/U +==================================================================== ========== + +.. [#] .. versionadded:: 3.25 On systems supporting macOS :prop_tgt:`FRAMEWORK` and :prop_tgt:`BUNDLE`, the following directories are searched for Frameworks or Application Bundles -containing a configuration file:: - - <prefix>/<name>.framework/Resources/ (A) - <prefix>/<name>.framework/Resources/CMake/ (A) - <prefix>/<name>.framework/Versions/*/Resources/ (A) - <prefix>/<name>.framework/Versions/*/Resources/CMake/ (A) - <prefix>/<name>.app/Contents/Resources/ (A) - <prefix>/<name>.app/Contents/Resources/CMake/ (A) +containing a configuration file: + +=========================================================== ========== + Entry Convention +=========================================================== ========== + ``<prefix>/<name>.framework/Resources/`` A + ``<prefix>/<name>.framework/Resources/CMake/`` A + ``<prefix>/<name>.framework/Versions/*/Resources/`` A + ``<prefix>/<name>.framework/Versions/*/Resources/CMake/`` A + ``<prefix>/<name>.app/Contents/Resources/`` A + ``<prefix>/<name>.app/Contents/Resources/CMake/`` A +=========================================================== ========== In all cases the ``<name>`` is treated as case-insensitive and corresponds to any of the names specified (``<PackageName>`` or names given by ``NAMES``). @@ -368,7 +379,7 @@ enabled. See policy :policy:`CMP0074`. 2. Search paths specified in cmake-specific cache variables. These - are intended to be used on the command line with a ``-DVAR=value``. + are intended to be used on the command line with a :option:`-DVAR=VALUE <cmake -D>`. The values are interpreted as :ref:`semicolon-separated lists <CMake Language Lists>`. This can be skipped if ``NO_CMAKE_PATH`` is passed or by setting the :variable:`CMAKE_FIND_USE_CMAKE_PATH` to ``FALSE``: diff --git a/Help/command/foreach.rst b/Help/command/foreach.rst index d9f54ca..ddf8dfa 100644 --- a/Help/command/foreach.rst +++ b/Help/command/foreach.rst @@ -130,3 +130,11 @@ yields -- en=two, ba=dua -- en=three, ba=tiga -- en=four, ba= + +See Also +^^^^^^^^ + +* :command:`break` +* :command:`continue` +* :command:`endforeach` +* :command:`while` diff --git a/Help/command/function.rst b/Help/command/function.rst index 3d25aa4..fc55c03 100644 --- a/Help/command/function.rst +++ b/Help/command/function.rst @@ -73,3 +73,9 @@ argument. Referencing to ``ARGV#`` arguments beyond ``ARGC`` have undefined behavior. Checking that ``ARGC`` is greater than ``#`` is the only way to ensure that ``ARGV#`` was passed to the function as an extra argument. + +See Also +^^^^^^^^ + +* :command:`endfunction` +* :command:`return` diff --git a/Help/command/get_test_property.rst b/Help/command/get_test_property.rst index e02b9bc..6bcc1ef 100644 --- a/Help/command/get_test_property.rst +++ b/Help/command/get_test_property.rst @@ -16,6 +16,7 @@ relevant parent scope as described for the :command:`define_property` command and if still unable to find the property, ``VAR`` will be set to an empty string. -For a list of standard properties you can type ``cmake --help-property-list``. +For a list of standard properties you can type +:option:`cmake --help-property-list`. See also the more general :command:`get_property` command. diff --git a/Help/command/if.rst b/Help/command/if.rst index 301cdce..b72769f 100644 --- a/Help/command/if.rst +++ b/Help/command/if.rst @@ -424,3 +424,10 @@ There is no automatic evaluation for environment or cache :ref:`Variable References`. Their values must be referenced as ``$ENV{<name>}`` or ``$CACHE{<name>}`` wherever the above-documented condition syntax accepts ``<variable|string>``. + +See also +^^^^^^^^ + + * :command:`else` + * :command:`elseif` + * :command:`endif` diff --git a/Help/command/install.rst b/Help/command/install.rst index 973aa31..feff436 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -132,7 +132,7 @@ Installing Targets install(TARGETS targets... [EXPORT <export-name>] [RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>] [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE| - PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>] + PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>|CXX_MODULES_BMI] [DESTINATION <dir>] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] @@ -215,11 +215,21 @@ that may be installed: ``/blah/include/myproj/here.h`` with a base directory ``/blah/include`` would be installed to ``myproj/here.h`` below the destination. +``CXX_MODULES_BMI`` + + .. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + + Any module files from C++ modules from ``PUBLIC`` sources in a file set of + type ``CXX_MODULES`` will be installed to the given ``DESTINATION``. All + modules are placed directly in the destination as no directory structure is + derived from the names of the modules. An empty ``DESTINATION`` may be used + to suppress installing these files (for use in generic code). + For each of these arguments given, the arguments following them only apply to the target or file type specified in the argument. If none is given, the -installation properties apply to all target types. If only one is given then -only targets of that type will be installed (which can be used to install -just a DLL or just an import library.) +installation properties apply to all target types. For regular executables, static libraries and shared libraries, the ``DESTINATION`` argument is not required. For these target types, when @@ -233,6 +243,14 @@ Apple bundles and frameworks. A destination can be omitted for interface and object libraries, but they are handled differently (see the discussion of this topic toward the end of this section). +For shared libraries on DLL platforms, if neither ``RUNTIME`` nor ``ARCHIVE`` +destinations are specified, both the ``RUNTIME`` and ``ARCHIVE`` components are +installed to their default destinations. If either a ``RUNTIME`` or ``ARCHIVE`` +destination is specified, the component is installed to that destination, and +the other component is not installed. If both ``RUNTIME`` and ``ARCHIVE`` +destinations are specified, then both components are installed to their +respective destinations. + The following table shows the target types with their associated variables and built-in defaults that apply when no destination is given: @@ -778,9 +796,10 @@ Installing Exports .. code-block:: cmake install(EXPORT <export-name> DESTINATION <dir> - [NAMESPACE <namespace>] [[FILE <name>.cmake]| + [NAMESPACE <namespace>] [FILE <name>.cmake] [PERMISSIONS permissions...] - [CONFIGURATIONS [Debug|Release|...]] + [CONFIGURATIONS [Debug|Release|...] + [CXX_MODULES_DIRECTORY <directory>] [EXPORT_LINK_INTERFACE_LIBRARIES] [COMPONENT <component>] [EXCLUDE_FROM_ALL]) @@ -836,6 +855,18 @@ library is always installed if the headers and CMake export file are present. to an ndk build system complete with transitive dependencies, include flags and defines required to use the libraries. +``CXX_MODULES_DIRECTORY`` + + .. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + + Specify a subdirectory to store C++ module information for targets in the + export set. This directory will be populated with files which add the + necessary target property information to the relevant targets. Note that + without this information, none of the C++ modules which are part of the + targets in the export set will support being imported in consuming targets. + The ``EXPORT`` form is useful to help outside projects use targets built and installed by the current project. For example, the code @@ -932,12 +963,12 @@ Generated Installation Script .. note:: Use of this feature is not recommended. Please consider using the - ``--install`` argument of :manual:`cmake(1)` instead. + :option:`cmake --install` instead. The ``install()`` command generates a file, ``cmake_install.cmake``, inside the build directory, which is used internally by the generated install target -and by CPack. You can also invoke this script manually with ``cmake -P``. This -script accepts several variables: +and by CPack. You can also invoke this script manually with +:option:`cmake -P`. This script accepts several variables: ``COMPONENT`` Set this variable to install only a single CPack component as opposed to all diff --git a/Help/command/message.rst b/Help/command/message.rst index ca4f5c1..77d21c8 100644 --- a/Help/command/message.rst +++ b/Help/command/message.rst @@ -83,8 +83,9 @@ are sent to stderr and are not prefixed with hyphens. The :manual:`CMake GUI <cmake-gui(1)>` displays all messages in its log area. The :manual:`curses interface <ccmake(1)>` shows ``STATUS`` to ``TRACE`` messages one at a time on a status line and other messages in an -interactive pop-up box. The ``--log-level`` command-line option to each of -these tools can be used to control which messages will be shown. +interactive pop-up box. The :option:`--log-level <cmake --log-level>` +command-line option to each of these tools can be used to control which +messages will be shown. .. versionadded:: 3.17 To make a log level persist between CMake runs, the @@ -104,7 +105,7 @@ these tools can be used to control which messages will be shown. list variable to a dot-separated string. The message context will always appear before any indenting content but after any automatically added leading hyphens. By default, message context is not shown, it has to be explicitly - enabled by giving the :manual:`cmake <cmake(1)>` ``--log-context`` + enabled by giving the :option:`cmake --log-context` command-line option or by setting the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` variable to true. See the :variable:`CMAKE_MESSAGE_CONTEXT` documentation for usage examples. diff --git a/Help/command/return.rst b/Help/command/return.rst index ec009d8..029fd05 100644 --- a/Help/command/return.rst +++ b/Help/command/return.rst @@ -5,7 +5,7 @@ Return from a file, directory or function. .. code-block:: cmake - return() + return([PROPAGATE <var-name>...]) Returns from a file, directory or function. When this command is encountered in an included file (via :command:`include` or @@ -16,5 +16,39 @@ deferred calls scheduled by :command:`cmake_language(DEFER)` are invoked and control is returned to the parent directory if there is one. If return is called in a function, control is returned to the caller of the function. +``PROPAGATE`` + .. versionadded:: 3.25 + + This option set or unset the specified variables in the parent directory or + function caller scope. This is equivalent to :command:`set(PARENT_SCOPE)` or + :command:`unset(PARENT_SCOPE)` commands. + + The option ``PROPAGATE`` can be very useful in conjunction with the + :command:`block` command because the :command:`return` will cross over + various scopes created by the :command:`block` commands. + + .. code-block:: cmake + + function(MULTI_SCOPES RESULT_VARIABLE) + block(SCOPE_FOR VARIABLES) + # here set(PARENT_SCOPE) is not usable because it will not set the + # variable in the caller scope but in the parent scope of the block() + set(${RESULT_VARIABLE} "new-value") + return(PROPAGATE ${RESULT_VARIABLE}) + endblock() + endfunction() + + set(MY_VAR "initial-value") + multi_scopes(MY_VAR) + # here MY_VAR will holds "new-value" + +Policy :policy:`CMP0140` controls the behavior regarding the arguments of the +command. + Note that a :command:`macro <macro>`, unlike a :command:`function <function>`, is expanded in place and therefore cannot handle ``return()``. + +See Also +^^^^^^^^ + + * :command:`block` diff --git a/Help/command/set.rst b/Help/command/set.rst index af862e4..90b57d2 100644 --- a/Help/command/set.rst +++ b/Help/command/set.rst @@ -22,12 +22,17 @@ Set Normal Variable Sets the given ``<variable>`` in the current function or directory scope. If the ``PARENT_SCOPE`` option is given the variable will be set in -the scope above the current scope. Each new directory or function -creates a new scope. This command will set the value of a variable -into the parent directory or calling function (whichever is applicable -to the case at hand). The previous state of the variable's value stays the -same in the current scope (e.g., if it was undefined before, it is still -undefined and if it had a value, it is still that value). +the scope above the current scope. Each new directory or :command:`function` +command creates a new scope. A scope can also be created with the +:command:`block` command. This command will set the value of a variable into +the parent directory, calling function or encompassing scope (whichever is +applicable to the case at hand). The previous state of the variable's value +stays the same in the current scope (e.g., if it was undefined before, it is +still undefined and if it had a value, it is still that value). + +The :command:`block(PROPAGATE)` and :command:`return(PROPAGATE)` commands can +be used as an alternate method to the :command:`set(PARENT_SCOPE)` and +:command:`unset(PARENT_SCOPE)` commands to update the parent scope. Set Cache Entry ^^^^^^^^^^^^^^^ @@ -78,7 +83,7 @@ option is given then the cache entry will be set to the given value. It is possible for the cache entry to exist prior to the call but have no type set if it was created on the :manual:`cmake(1)` command -line by a user through the ``-D<var>=<value>`` option without +line by a user through the :option:`-D\<var\>=\<value\> <cmake -D>` option without specifying a type. In this case the ``set`` command will add the type. Furthermore, if the ``<type>`` is ``PATH`` or ``FILEPATH`` and the ``<value>`` provided on the command line is a relative path, diff --git a/Help/command/target_compile_definitions.rst b/Help/command/target_compile_definitions.rst index 3fb113a..2d292af 100644 --- a/Help/command/target_compile_definitions.rst +++ b/Help/command/target_compile_definitions.rst @@ -15,9 +15,9 @@ named ``<target>`` must have been created by a command such as :ref:`ALIAS target <Alias Targets>`. The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to -specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC`` -items will populate the :prop_tgt:`COMPILE_DEFINITIONS` property of -``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the +specify the :ref:`scope <Target Usage Requirements>` of the following arguments. +``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`COMPILE_DEFINITIONS` +property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the :prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` property of ``<target>``. The following arguments specify compile definitions. Repeated calls for the same ``<target>`` append items in the order called. diff --git a/Help/command/target_compile_options.rst b/Help/command/target_compile_options.rst index e45b209..0d86c91 100644 --- a/Help/command/target_compile_options.rst +++ b/Help/command/target_compile_options.rst @@ -22,9 +22,9 @@ If ``BEFORE`` is specified, the content will be prepended to the property instead of being appended. The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to -specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC`` -items will populate the :prop_tgt:`COMPILE_OPTIONS` property of -``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the +specify the :ref:`scope <Target Usage Requirements>` of the following arguments. +``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`COMPILE_OPTIONS` +property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the :prop_tgt:`INTERFACE_COMPILE_OPTIONS` property of ``<target>``. The following arguments specify compile options. Repeated calls for the same ``<target>`` append items in the order called. diff --git a/Help/command/target_include_directories.rst b/Help/command/target_include_directories.rst index 9a99a7d..f13ff29 100644 --- a/Help/command/target_include_directories.rst +++ b/Help/command/target_include_directories.rst @@ -18,9 +18,9 @@ By using ``AFTER`` or ``BEFORE`` explicitly, you can select between appending and prepending, independent of the default. The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to specify -the scope of the following arguments. ``PRIVATE`` and ``PUBLIC`` items will -populate the :prop_tgt:`INCLUDE_DIRECTORIES` property of ``<target>``. -``PUBLIC`` and ``INTERFACE`` items will populate the +the :ref:`scope <Target Usage Requirements>` of the following arguments. +``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`INCLUDE_DIRECTORIES` +property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` property of ``<target>``. The following arguments specify include directories. diff --git a/Help/command/target_link_directories.rst b/Help/command/target_link_directories.rst index bb75a3d..b72f746 100644 --- a/Help/command/target_link_directories.rst +++ b/Help/command/target_link_directories.rst @@ -21,11 +21,12 @@ The named ``<target>`` must have been created by a command such as :ref:`ALIAS target <Alias Targets>`. The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to -specify the scope of the items that follow them. ``PRIVATE`` and -``PUBLIC`` items will populate the :prop_tgt:`LINK_DIRECTORIES` property -of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the -:prop_tgt:`INTERFACE_LINK_DIRECTORIES` property of ``<target>`` -(:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items). +specify the :ref:`scope <Target Usage Requirements>` of the items that follow +them. ``PRIVATE`` and ``PUBLIC`` items will populate the +:prop_tgt:`LINK_DIRECTORIES` property of ``<target>``. ``PUBLIC`` and +``INTERFACE`` items will populate the :prop_tgt:`INTERFACE_LINK_DIRECTORIES` +property of ``<target>`` (:ref:`IMPORTED targets <Imported Targets>` only +support ``INTERFACE`` items). Each item specifies a link directory and will be converted to an absolute path if necessary before adding it to the relevant property. Repeated calls for the same ``<target>`` append items in the order called. diff --git a/Help/command/target_link_libraries.rst b/Help/command/target_link_libraries.rst index c85094a..bb7b5cc 100644 --- a/Help/command/target_link_libraries.rst +++ b/Help/command/target_link_libraries.rst @@ -146,8 +146,10 @@ Libraries for a Target and/or its Dependents <PRIVATE|PUBLIC|INTERFACE> <item>... [<PRIVATE|PUBLIC|INTERFACE> <item>...]...) -The ``PUBLIC``, ``PRIVATE`` and ``INTERFACE`` keywords can be used to +The ``PUBLIC``, ``PRIVATE`` and ``INTERFACE`` +:ref:`scope <Target Usage Requirements>` keywords can be used to specify both the link dependencies and the link interface in one command. + Libraries and targets following ``PUBLIC`` are linked to, and are made part of the link interface. Libraries and targets following ``PRIVATE`` are linked to, but are not made part of the link interface. Libraries diff --git a/Help/command/target_link_options.rst b/Help/command/target_link_options.rst index 87dff39..3cd0e64 100644 --- a/Help/command/target_link_options.rst +++ b/Help/command/target_link_options.rst @@ -32,9 +32,9 @@ If ``BEFORE`` is specified, the content will be prepended to the property instead of being appended. The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to -specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC`` -items will populate the :prop_tgt:`LINK_OPTIONS` property of -``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the +specify the :ref:`scope <Target Usage Requirements>` of the following arguments. +``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`LINK_OPTIONS` +property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the :prop_tgt:`INTERFACE_LINK_OPTIONS` property of ``<target>``. The following arguments specify link options. Repeated calls for the same ``<target>`` append items in the order called. diff --git a/Help/command/target_precompile_headers.rst b/Help/command/target_precompile_headers.rst index 9f7dabb..84f5d12 100644 --- a/Help/command/target_precompile_headers.rst +++ b/Help/command/target_precompile_headers.rst @@ -25,9 +25,9 @@ The named ``<target>`` must have been created by a command such as :ref:`ALIAS target <Alias Targets>`. The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to -specify the scope of the following arguments. ``PRIVATE`` and ``PUBLIC`` -items will populate the :prop_tgt:`PRECOMPILE_HEADERS` property of -``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the +specify the :ref:`scope <Target Usage Requirements>` of the following arguments. +``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`PRECOMPILE_HEADERS` +property of ``<target>``. ``PUBLIC`` and ``INTERFACE`` items will populate the :prop_tgt:`INTERFACE_PRECOMPILE_HEADERS` property of ``<target>`` (:ref:`IMPORTED targets <Imported Targets>` only support ``INTERFACE`` items). Repeated calls for the same ``<target>`` will append items in the order called. diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst index 72119f6..461175a 100644 --- a/Help/command/target_sources.rst +++ b/Help/command/target_sources.rst @@ -22,10 +22,10 @@ The named ``<target>`` must have been created by a command such as ``<target>`` can be a custom target. The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to -specify the scope of the source file paths (``<items>``) that follow -them. ``PRIVATE`` and ``PUBLIC`` items will populate the :prop_tgt:`SOURCES` -property of ``<target>``, which are used when building the target itself. -``PUBLIC`` and ``INTERFACE`` items will populate the +specify the :ref:`scope <Target Usage Requirements>` of the source file paths +(``<items>``) that follow them. ``PRIVATE`` and ``PUBLIC`` items will +populate the :prop_tgt:`SOURCES` property of ``<target>``, which are used when +building the target itself. ``PUBLIC`` and ``INTERFACE`` items will populate the :prop_tgt:`INTERFACE_SOURCES` property of ``<target>``, which are used when building dependents. A target created by :command:`add_custom_target` can only have ``PRIVATE`` scope. @@ -75,9 +75,33 @@ File Sets Adds a file set to a target, or adds files to an existing file set. Targets have zero or more named file sets. Each file set has a name, a type, a scope of ``INTERFACE``, ``PUBLIC``, or ``PRIVATE``, one or more base directories, and -files within those directories. The only acceptable type is ``HEADERS``. The -optional default file sets are named after their type. The target may not be a -custom target or :prop_tgt:`FRAMEWORK` target. +files within those directories. The acceptable types include: + +``HEADERS`` + + Sources intended to be used via a language's ``#include`` mechanism. + +``CXX_MODULES`` + + .. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + + Sources which contain C++ interface module or partition units (i.e., those + using the ``export`` keyword). This file set type may not have an + ``INTERFACE`` scope except on ``IMPORTED`` targets. + +``CXX_MODULE_HEADER_UNITS`` + + .. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + + C++ header sources which may be imported by other C++ source code. This file + set type may not have an ``INTERFACE`` scope except on ``IMPORTED`` targets. + +The optional default file sets are named after their type. The target may not +be a custom target or :prop_tgt:`FRAMEWORK` target. Files in a ``PRIVATE`` or ``PUBLIC`` file set are marked as source files for the purposes of IDE integration. Additionally, files in ``HEADERS`` file sets @@ -93,16 +117,17 @@ Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``, o The name of the file set to create or add to. It must contain only letters, numbers and underscores. Names starting with a capital letter are reserved - for built-in file sets predefined by CMake. The only predefined set name is - ``HEADERS``. All other set names must not start with a capital letter or + for built-in file sets predefined by CMake. The only predefined set names + are those matching the acceptable types. All other set names must not start + with a capital letter or underscore. ``TYPE <type>`` - Every file set is associated with a particular type of file. ``HEADERS`` - is currently the only defined type and it is an error to specify anything - else. As a special case, if the name of the file set is ``HEADERS``, the - type does not need to be specified and the ``TYPE <type>`` arguments can be + Every file set is associated with a particular type of file. Only types + specified above may be used and it is an error to specify anything else. As + a special case, if the name of the file set is one of the types, the type + does not need to be specified and the ``TYPE <type>`` arguments can be omitted. For all other file set names, ``TYPE`` is required. ``BASE_DIRS <dirs>...`` @@ -134,6 +159,8 @@ Each ``target_sources(FILE_SET)`` entry starts with ``INTERFACE``, ``PUBLIC``, o The following target properties are set by ``target_sources(FILE_SET)``, but they should not generally be manipulated directly: +For file sets of type ``HEADERS``: + * :prop_tgt:`HEADER_SETS` * :prop_tgt:`INTERFACE_HEADER_SETS` * :prop_tgt:`HEADER_SET` @@ -141,17 +168,37 @@ but they should not generally be manipulated directly: * :prop_tgt:`HEADER_DIRS` * :prop_tgt:`HEADER_DIRS_<NAME>` +For file sets of type ``CXX_MODULES``: + +* :prop_tgt:`CXX_MODULE_SETS` +* :prop_tgt:`INTERFACE_CXX_MODULE_SETS` +* :prop_tgt:`CXX_MODULE_SET` +* :prop_tgt:`CXX_MODULE_SET_<NAME>` +* :prop_tgt:`CXX_MODULE_DIRS` +* :prop_tgt:`CXX_MODULE_DIRS_<NAME>` + +For file sets of type ``CXX_MODULE_HEADER_UNITS``: + +* :prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS` +* :prop_tgt:`INTERFACE_CXX_MODULE_HEADER_UNIT_SETS` +* :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET` +* :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET_<NAME>` +* :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS` +* :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS_<NAME>` + Target properties related to include directories are also modified by ``target_sources(FILE_SET)`` as follows: :prop_tgt:`INCLUDE_DIRECTORIES` - If the ``TYPE`` is ``HEADERS``, and the scope of the file set is ``PRIVATE`` - or ``PUBLIC``, all of the ``BASE_DIRS`` of the file set are wrapped in - :genex:`$<BUILD_INTERFACE>` and appended to this property. + If the ``TYPE`` is ``HEADERS`` or ``CXX_MODULE_HEADER_UNITS``, and the scope + of the file set is ``PRIVATE`` or ``PUBLIC``, all of the ``BASE_DIRS`` of + the file set are wrapped in :genex:`$<BUILD_INTERFACE>` and appended to this + property. :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` - If the ``TYPE`` is ``HEADERS``, and the scope of the file set is - ``INTERFACE`` or ``PUBLIC``, all of the ``BASE_DIRS`` of the file set are - wrapped in :genex:`$<BUILD_INTERFACE>` and appended to this property. + If the ``TYPE`` is ``HEADERS`` or ``CXX_MODULE_HEADER_UNITS``, and the scope + of the file set is ``INTERFACE`` or ``PUBLIC``, all of the ``BASE_DIRS`` of + the file set are wrapped in :genex:`$<BUILD_INTERFACE>` and appended to this + property. diff --git a/Help/command/try_compile.rst b/Help/command/try_compile.rst index 806a98d..9e9f39f 100644 --- a/Help/command/try_compile.rst +++ b/Help/command/try_compile.rst @@ -14,10 +14,16 @@ Try Compiling Whole Projects .. code-block:: cmake - try_compile(<resultVar> <bindir> <srcdir> - <projectName> [<targetName>] [CMAKE_FLAGS <flags>...] + try_compile(<resultVar> PROJECT <projectName> + SOURCE_DIR <srcdir> + [BINARY_DIR <bindir>] + [TARGET <targetName>] + [NO_CACHE] + [CMAKE_FLAGS <flags>...] [OUTPUT_VARIABLE <var>]) +.. versionadded:: 3.25 + Try building a project. The success or failure of the ``try_compile``, i.e. ``TRUE`` or ``FALSE`` respectively, is returned in ``<resultVar>``. @@ -34,6 +40,17 @@ below for the meaning of other options. Previously this was only done by the :ref:`source file <Try Compiling Source Files>` signature. +This command also supports an alternate signature +which was present in older versions of CMake: + +.. code-block:: cmake + + try_compile(<resultVar> <bindir> <srcdir> + <projectName> [<targetName>] + [NO_CACHE] + [CMAKE_FLAGS <flags>...] + [OUTPUT_VARIABLE <var>]) + .. _`Try Compiling Source Files`: Try Compiling Source Files @@ -41,7 +58,12 @@ Try Compiling Source Files .. code-block:: cmake - try_compile(<resultVar> <bindir> <srcfile|SOURCES srcfile...> + try_compile(<resultVar> + <SOURCES <srcfile...> | + SOURCE_FROM_CONTENT <name> <content> | + SOURCE_FROM_VAR <name> <var> | + SOURCE_FROM_FILE <name> <path> >... + [NO_CACHE] [CMAKE_FLAGS <flags>...] [COMPILE_DEFINITIONS <defs>...] [LINK_OPTIONS <options>...] @@ -53,15 +75,19 @@ Try Compiling Source Files [<LANG>_EXTENSIONS <bool>] ) +.. versionadded:: 3.25 + Try building an executable or static library from one or more source files (which one is determined by the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable). The success or failure of the ``try_compile``, i.e. ``TRUE`` or ``FALSE`` respectively, is returned in ``<resultVar>``. -In this form, one or more source files must be provided. If -:variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is unset or is set to ``EXECUTABLE``, -the sources must include a definition for ``main`` and CMake will create a -``CMakeLists.txt`` file to build the source(s) as an executable. +In this form, one or more source files must be provided. Additionally, one of +``SOURCES`` and/or ``SOURCE_FROM_*`` must precede other keywords. + +If :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is unset or is set to +``EXECUTABLE``, the sources must include a definition for ``main`` and CMake +will create a ``CMakeLists.txt`` file to build the source(s) as an executable. If :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` is set to ``STATIC_LIBRARY``, a static library will be built instead and no definition for ``main`` is required. For an executable, the generated ``CMakeLists.txt`` file would @@ -76,11 +102,45 @@ contain something like the following: target_link_options(cmTryCompileExec PRIVATE <LINK_OPTIONS from caller>) target_link_libraries(cmTryCompileExec ${LINK_LIBRARIES}) +CMake automatically generates, for each ``try_compile`` operation, a +unique directory under ``${CMAKE_BINARY_DIR}/CMakeFiles/CMakeScratch`` +with an unspecified name. These directories are cleaned automatically unless +:option:`--debug-trycompile <cmake --debug-trycompile>` is passed to ``cmake``. +Such directories from previous runs are also unconditionally cleaned at the +beginning of any ``cmake`` execution. + +This command also supports an alternate signature +which was present in older versions of CMake: + +.. code-block:: cmake + + try_compile(<resultVar> <bindir> <srcfile|SOURCES srcfile...> + [NO_CACHE] + [CMAKE_FLAGS <flags>...] + [COMPILE_DEFINITIONS <defs>...] + [LINK_OPTIONS <options>...] + [LINK_LIBRARIES <libs>...] + [OUTPUT_VARIABLE <var>] + [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]] + [<LANG>_STANDARD <std>] + [<LANG>_STANDARD_REQUIRED <bool>] + [<LANG>_EXTENSIONS <bool>] + ) + +In this version, ``try_compile`` will use ``<bindir>/CMakeFiles/CMakeTmp`` for +its operation, and all such files will be cleaned automatically. +For debugging, :option:`--debug-trycompile <cmake --debug-trycompile>` can be +passed to ``cmake`` to avoid this clean. However, multiple sequential +``try_compile`` operations, if given the same ``<bindir>``, will reuse this +single output directory, such that you can only debug one such ``try_compile`` +call at a time. Use of the newer signature is recommended to simplify +debugging of multiple ``try_compile`` operations. + The options are: ``CMAKE_FLAGS <flags>...`` - Specify flags of the form ``-DVAR:TYPE=VALUE`` to be passed to - the ``cmake`` command-line used to drive the test build. + Specify flags of the form :option:`-DVAR:TYPE=VALUE <cmake -D>` to be passed + to the :manual:`cmake(1)` command-line used to drive the test build. The above example shows how values for variables ``INCLUDE_DIRECTORIES``, ``LINK_DIRECTORIES``, and ``LINK_LIBRARIES`` are used. @@ -111,9 +171,61 @@ The options are: set the :prop_tgt:`STATIC_LIBRARY_OPTIONS` target property in the generated project, depending on the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable. +``NO_CACHE`` + .. versionadded:: 3.25 + + The result will be stored in a normal variable rather than a cache entry. + + The result variable is normally cached so that a simple pattern can be used + to avoid repeating the test on subsequent executions of CMake: + + .. code-block:: cmake + + if(NOT DEFINED RESULTVAR) + # ...(check-specific setup code)... + try_compile(RESULTVAR ...) + # ...(check-specific logging and cleanup code)... + endif() + + If the guard variable and result variable are not the same (for example, if + the test is part of a larger inspection), ``NO_CACHE`` may be useful to avoid + leaking the intermediate result variable into the cache. + ``OUTPUT_VARIABLE <var>`` Store the output from the build process in the given variable. +``SOURCE_FROM_CONTENT <name> <content>`` + .. versionadded:: 3.25 + + Write ``<content>`` to a file named ``<name>`` in the operation directory. + This can be used to bypass the need to separately write a source file when + the contents of the file are dynamically specified. The specified ``<name>`` + is not allowed to contain path components. + + ``SOURCE_FROM_CONTENT`` may be specified multiple times. + +``SOURCE_FROM_FILE <name> <path>`` + .. versionadded:: 3.25 + + Copy ``<path>`` to a file named ``<name>`` in the operation directory. This + can be used to consolidate files into the operation directory, which may be + useful if a source which already exists (i.e. as a stand-alone file in a + project's source repository) needs to refer to other file(s) created by + ``SOURCE_FROM_*``. (Otherwise, ``SOURCES`` is usually more convenient.) The + specified ``<name>`` is not allowed to contain path components. + +``SOURCE_FROM_VAR <name> <var>`` + .. versionadded:: 3.25 + + Write the contents of ``<var>`` to a file named ``<name>`` in the operation + directory. This is the same as ``SOURCE_FROM_CONTENT``, but takes the + contents from the specified CMake variable, rather than directly, which may + be useful when passing arguments through a function which wraps + ``try_compile``. The specified ``<name>`` is not allowed to contain path + components. + + ``SOURCE_FROM_VAR`` may be specified multiple times. + ``<LANG>_STANDARD <std>`` .. versionadded:: 3.8 @@ -136,17 +248,6 @@ The options are: :prop_tgt:`OBJC_EXTENSIONS`, :prop_tgt:`OBJCXX_EXTENSIONS`, or :prop_tgt:`CUDA_EXTENSIONS` target property of the generated project. -In this version all files in ``<bindir>/CMakeFiles/CMakeTmp`` will be -cleaned automatically. For debugging, ``--debug-trycompile`` can be -passed to ``cmake`` to avoid this clean. However, multiple sequential -``try_compile`` operations reuse this single output directory. If you use -``--debug-trycompile``, you can only debug one ``try_compile`` call at a time. -The recommended procedure is to protect all ``try_compile`` calls in your -project by ``if(NOT DEFINED <resultVar>)`` logic, configure with cmake -all the way through once, then delete the cache entry associated with -the try_compile call of interest, and then re-run cmake again with -``--debug-trycompile``. - Other Behavior Settings ^^^^^^^^^^^^^^^^^^^^^^^ @@ -214,9 +315,15 @@ a build configuration. the generated project (unless overridden by an explicit option). .. versionchanged:: 3.14 - For the :generator:`Green Hills MULTI` generator the GHS toolset and target - system customization cache variables are also propagated into the test project. + For the :generator:`Green Hills MULTI` generator, the GHS toolset and target + system customization cache variables are also propagated into the test + project. .. versionadded:: 3.24 The :variable:`CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES` variable may be set to disable passing platform variables into the test project. + +.. versionadded:: 3.25 + If :policy:`CMP0141` is set to ``NEW``, one can use + :variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` to specify the MSVC debug + information format. diff --git a/Help/command/try_run.rst b/Help/command/try_run.rst index fc41cdd..cd41a4b 100644 --- a/Help/command/try_run.rst +++ b/Help/command/try_run.rst @@ -13,68 +13,99 @@ Try Compiling and Running Source Files .. code-block:: cmake try_run(<runResultVar> <compileResultVar> - <bindir> <srcfile> [CMAKE_FLAGS <flags>...] + <SOURCES <srcfile...> | + SOURCE_FROM_CONTENT <name> <content> | + SOURCE_FROM_VAR <name> <var> | + SOURCE_FROM_FILE <name> <path> >... + [NO_CACHE] + [CMAKE_FLAGS <flags>...] [COMPILE_DEFINITIONS <defs>...] [LINK_OPTIONS <options>...] [LINK_LIBRARIES <libs>...] [COMPILE_OUTPUT_VARIABLE <var>] + [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]] + [<LANG>_STANDARD <std>] + [<LANG>_STANDARD_REQUIRED <bool>] + [<LANG>_EXTENSIONS <bool>] [RUN_OUTPUT_VARIABLE <var>] + [RUN_OUTPUT_STDOUT_VARIABLE <var>] + [RUN_OUTPUT_STDERR_VARIABLE <var>] [OUTPUT_VARIABLE <var>] [WORKING_DIRECTORY <var>] - [ARGS <args>...]) + [ARGS <args>...] + ) + +.. versionadded:: 3.25 Try compiling a ``<srcfile>``. Returns ``TRUE`` or ``FALSE`` for success or failure in ``<compileResultVar>``. If the compile succeeded, runs the executable and returns its exit code in ``<runResultVar>``. If the executable was built, but failed to run, then ``<runResultVar>`` will be set to ``FAILED_TO_RUN``. See the :command:`try_compile` command for -information on how the test project is constructed to build the source file. - -The options are: - -``CMAKE_FLAGS <flags>...`` - Specify flags of the form ``-DVAR:TYPE=VALUE`` to be passed to - the ``cmake`` command-line used to drive the test build. - The example in :command:`try_compile` shows how values for variables - ``INCLUDE_DIRECTORIES``, ``LINK_DIRECTORIES``, and ``LINK_LIBRARIES`` - are used. +documentation of options common to both commands, and for information on how +the test project is constructed to build the source file. -``COMPILE_DEFINITIONS <defs>...`` - Specify ``-Ddefinition`` arguments to pass to :command:`add_definitions` - in the generated test project. - -``COMPILE_OUTPUT_VARIABLE <var>`` - Report the compile step build output in a given variable. +One or more source files must be provided. Additionally, one of ``SOURCES`` +and/or ``SOURCE_FROM_*`` must precede other keywords. -``LINK_LIBRARIES <libs>...`` - .. versionadded:: 3.2 +This command also supports an alternate signature +which was present in older versions of CMake: - Specify libraries to be linked in the generated project. - The list of libraries may refer to system libraries and to - :ref:`Imported Targets <Imported Targets>` from the calling project. +.. code-block:: cmake - If this option is specified, any ``-DLINK_LIBRARIES=...`` value - given to the ``CMAKE_FLAGS`` option will be ignored. + try_run(<runResultVar> <compileResultVar> + <bindir> <srcfile|SOURCES srcfile...> + [NO_CACHE] + [CMAKE_FLAGS <flags>...] + [COMPILE_DEFINITIONS <defs>...] + [LINK_OPTIONS <options>...] + [LINK_LIBRARIES <libs>...] + [COMPILE_OUTPUT_VARIABLE <var>] + [COPY_FILE <fileName> [COPY_FILE_ERROR <var>]] + [<LANG>_STANDARD <std>] + [<LANG>_STANDARD_REQUIRED <bool>] + [<LANG>_EXTENSIONS <bool>] + [RUN_OUTPUT_VARIABLE <var>] + [RUN_OUTPUT_STDOUT_VARIABLE <var>] + [RUN_OUTPUT_STDERR_VARIABLE <var>] + [OUTPUT_VARIABLE <var>] + [WORKING_DIRECTORY <var>] + [ARGS <args>...] + ) -``LINK_OPTIONS <options>...`` - .. versionadded:: 3.14 +The options specific to ``try_run`` are: - Specify link step options to pass to :command:`target_link_options` in the - generated project. +``COMPILE_OUTPUT_VARIABLE <var>`` + Report the compile step build output in a given variable. ``OUTPUT_VARIABLE <var>`` Report the compile build output and the output from running the executable - in the given variable. This option exists for legacy reasons. Prefer - ``COMPILE_OUTPUT_VARIABLE`` and ``RUN_OUTPUT_VARIABLE`` instead. + in the given variable. This option exists for legacy reasons and is only + supported by the old ``try_run`` signature. + Prefer ``COMPILE_OUTPUT_VARIABLE`` and ``RUN_OUTPUT_VARIABLE`` instead. ``RUN_OUTPUT_VARIABLE <var>`` Report the output from running the executable in a given variable. +``RUN_OUTPUT_STDOUT_VARIABLE <var>`` + .. versionadded:: 3.25 + + Report the output of stdout from running the executable in a given variable. + +``RUN_OUTPUT_STDERR_VARIABLE <var>`` + .. versionadded:: 3.25 + + Report the output of stderr from running the executable in a given variable. + ``WORKING_DIRECTORY <var>`` .. versionadded:: 3.20 Run the executable in the given directory. If no ``WORKING_DIRECTORY`` is - specified, the executable will run in ``<bindir>``. + specified, the executable will run in ``<bindir>`` or the current build + directory. + +``ARGS <args>...`` + Additional arguments to pass to the executable when running it. Other Behavior Settings ^^^^^^^^^^^^^^^^^^^^^^^ @@ -110,6 +141,7 @@ These cache entries are: In order to make cross compiling your project easier, use ``try_run`` only if really required. If you use ``try_run``, use the +``RUN_OUTPUT_STDOUT_VARIABLE``, ``RUN_OUTPUT_STDERR_VARIABLE``, ``RUN_OUTPUT_VARIABLE`` or ``OUTPUT_VARIABLE`` options only if really required. Using them will require that when cross-compiling, the cache variables will have to be set manually to the output of the executable. diff --git a/Help/command/while.rst b/Help/command/while.rst index a4957c1..0bafae5 100644 --- a/Help/command/while.rst +++ b/Help/command/while.rst @@ -23,3 +23,11 @@ Per legacy, the :command:`endwhile` command admits an optional ``<condition>`` argument. If used, it must be a verbatim repeat of the argument of the opening ``while`` command. + +See Also +^^^^^^^^ + + * :command:`break` + * :command:`continue` + * :command:`foreach` + * :command:`endwhile` diff --git a/Help/cpack_gen/archive.rst b/Help/cpack_gen/archive.rst index a77b615..9df3cc4 100644 --- a/Help/cpack_gen/archive.rst +++ b/Help/cpack_gen/archive.rst @@ -57,6 +57,12 @@ Variables specific to CPack Archive generator .. versionadded:: 3.9 Per-component ``CPACK_ARCHIVE_<component>_FILE_NAME`` variables. +.. variable:: CPACK_ARCHIVE_FILE_EXTENSION + + .. versionadded:: 3.25 + + Package file extension. Default values are given in the list above. + .. variable:: CPACK_ARCHIVE_COMPONENT_INSTALL Enable component packaging. If enabled (ON), then the archive generator diff --git a/Help/cpack_gen/external.rst b/Help/cpack_gen/external.rst index 4c083f0..b511319 100644 --- a/Help/cpack_gen/external.rst +++ b/Help/cpack_gen/external.rst @@ -207,8 +207,8 @@ following fields in the root: set. ``buildConfig`` - The build configuration given to CPack with the ``-C`` option. Only present - if this option is set. + The build configuration given to CPack with the :option:`cpack -C` option. + Only present if this option is set. ``defaultDirectoryPermissions`` The default directory permissions given in diff --git a/Help/cpack_gen/freebsd.rst b/Help/cpack_gen/freebsd.rst index f429bc5..faf8c74 100644 --- a/Help/cpack_gen/freebsd.rst +++ b/Help/cpack_gen/freebsd.rst @@ -62,8 +62,6 @@ the RPM information (e.g. package license). - :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` (this is always set by CPack itself, if nothing else sets it explicitly). - - :variable:`PROJECT_DESCRIPTION` (this can be set with the DESCRIPTION - parameter for :command:`project`). .. variable:: CPACK_FREEBSD_PACKAGE_DESCRIPTION @@ -75,6 +73,10 @@ the RPM information (e.g. package license). - :variable:`CPACK_DEBIAN_PACKAGE_DESCRIPTION` (this may be set already for Debian packaging, so it is used as a fallback). + - :variable:`CPACK_PACKAGE_DESCRIPTION_SUMMARY` (this is always set + by CPack itself, if nothing else sets it explicitly). + - :variable:`PROJECT_DESCRIPTION` (this can be set with the DESCRIPTION + parameter for :command:`project`). .. variable:: CPACK_FREEBSD_PACKAGE_WWW @@ -85,12 +87,12 @@ the RPM information (e.g. package license). * Mandatory: YES * Default: - - :variable:`CMAKE_PROJECT_HOMEPAGE_URL`, or if that is not set, - :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already + - :variable:`CPACK_PACKAGE_HOMEPAGE_URL`, or if that is not set, + - :variable:`CPACK_DEBIAN_PACKAGE_HOMEPAGE` (this may be set already for Debian packaging, so it is used as a fallback). .. versionadded:: 3.12 - The ``CMAKE_PROJECT_HOMEPAGE_URL`` variable. + The ``CPACK_PACKAGE_HOMEPAGE_URL`` variable. .. variable:: CPACK_FREEBSD_PACKAGE_LICENSE diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst index 299cfec..df306c2 100644 --- a/Help/cpack_gen/nsis.rst +++ b/Help/cpack_gen/nsis.rst @@ -207,3 +207,34 @@ on Windows Nullsoft Scriptable Install System. .. versionadded:: 3.22 If set, do not display the page containing the license during installation. + +.. variable:: CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS + + .. versionadded:: 3.25 + + This variable is a :ref:`semicolon-separated list <CMake Language Lists>` of + arguments to prepend to the nsis script to run. + If the arguments do not start with a ``/`` or a ``-``, it will add one + automatically to the corresponding arguments. + The command that will be run is:: + + makensis.exe <preArgs>... "nsisFileName.nsi" <postArgs>... + + where ``<preArgs>...`` is constructed from ``CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS`` + and ``<postArgs>...`` is constructed from ``CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS``. + + +.. variable:: CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS + + .. versionadded:: 3.25 + + This variable is a :ref:`semicolon-separated list <CMake Language Lists>` of + arguments to append to the nsis script to run. + If the arguments do not start with a ``/`` or a ``-``, it will add one + automatically to the corresponding arguments. + The command that will be run is:: + + makensis.exe <preArgs>... "nsisFileName.nsi" <postArgs>... + + where ``<preArgs>...`` is constructed from ``CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS`` + and ``<postArgs>...`` is constructed from ``CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS``. diff --git a/Help/cpack_gen/nuget.rst b/Help/cpack_gen/nuget.rst index c980dd6..3bc73aa 100644 --- a/Help/cpack_gen/nuget.rst +++ b/Help/cpack_gen/nuget.rst @@ -162,6 +162,14 @@ List of CPack NuGet generator specific variables: * Mandatory : NO * Default : - +.. variable:: CPACK_NUGET_PACKAGE_REQUIRE_LICENSE_ACCEPTANCE + + When set to a true value, the user will be prompted to accept the license + before installing the package. + + * Mandatory : NO + * Default : - + .. variable:: CPACK_NUGET_PACKAGE_ICON CPACK_NUGET_<compName>_PACKAGE_ICON diff --git a/Help/cpack_gen/rpm.rst b/Help/cpack_gen/rpm.rst index 0d287fc..13b7255 100644 --- a/Help/cpack_gen/rpm.rst +++ b/Help/cpack_gen/rpm.rst @@ -972,7 +972,7 @@ For CMake projects SRPM package would be produced by executing:: Produced SRPM package is expected to be built with :manual:`cmake(1)` executable and packaged with :manual:`cpack(1)` executable so CMakeLists.txt has to be located in root source directory and must be able to generate binary rpm - packages by executing ``cpack -G`` command. The two executables as well as + packages by executing :option:`cpack -G` command. The two executables as well as rpmbuild must also be present when generating binary rpm packages from the produced SRPM package. diff --git a/Help/dev/experimental.rst b/Help/dev/experimental.rst index 7638d22..adfa36f 100644 --- a/Help/dev/experimental.rst +++ b/Help/dev/experimental.rst @@ -7,6 +7,23 @@ See documentation on `CMake Development`_ for more information. .. _`CMake Development`: README.rst +Features are gated behind ``CMAKE_EXPERIMENTAL_`` variables which must be set +to specific values in order to enable their gated behaviors. Note that the +specific values will change over time to reinforce their experimental nature. +When used, a warning will be generated to indicate that an experimental +feature is in use and that the affected behavior in the project is not part of +CMake's stability guarantees. + +C++20 Module APIs +================= + +Variable: ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` +Value: ``3c375311-a3c9-4396-a187-3227ef642046`` + +In order to support C++20 modules, there are a number of behaviors that have +CMake APIs to provide the required features to build and export them from a +project. + C++20 Module Dependencies ========================= @@ -40,13 +57,8 @@ dependencies to the file specified by the ``<DYNDEP_FILE>`` placeholder. The ``CMAKE_EXPERIMENTAL_CXX_SCANDEP_DEPFILE_FORMAT`` file may be set to ``msvc`` for scandep rules which use ``msvc``-style dependency reporting. -For tools which need to know the file set the source belongs to, the -``CMAKE_EXPERIMENTAL_CXX_MODULE_SOURCE_TYPE_FLAG_<FILE_SET_TYPE>`` flag may -be provided so that different source types can be distinguished prior to -scanning. - The module dependencies should be written in the format described -by the `P1689r4`_ paper. +by the `P1689r5`_ paper. Compiler writers may try out their scanning functionality using the `cxx-modules-sandbox`_ test project, modified to set variables @@ -73,5 +85,5 @@ the GCC documentation, but the relevant section for the purposes of CMake is: -- GCC module mapper documentation .. _`D1483r1`: https://mathstuf.fedorapeople.org/fortran-modules/fortran-modules.html -.. _`P1689r4`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1689r4.html +.. _`P1689r5`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1689r5.html .. _`cxx-modules-sandbox`: https://github.com/mathstuf/cxx-modules-sandbox diff --git a/Help/envvar/ASM_DIALECTFLAGS.rst b/Help/envvar/ASM_DIALECTFLAGS.rst index 2e1c6d2..2af4b58 100644 --- a/Help/envvar/ASM_DIALECTFLAGS.rst +++ b/Help/envvar/ASM_DIALECTFLAGS.rst @@ -3,13 +3,16 @@ ASM<DIALECT>FLAGS .. include:: ENV_VAR.txt -Default compilation flags to be used when compiling a specific dialect of an -assembly language. ``ASM<DIALECT>FLAGS`` can be ``ASMFLAGS``, ``ASM_NASMFLAGS``, -``ASM_MASMFLAGS`` or ``ASM-ATTFLAGS``. Will only be used by CMake on the -first configuration to determine ``ASM_<DIALECT>`` default compilation -flags, after which the value for ``ASM<DIALECT>FLAGS`` is stored in the cache -as ``CMAKE_ASM<DIALECT>_FLAGS <CMAKE_<LANG>_FLAGS>``. For any configuration -run (including the first), the environment variable will be ignored, if the -``CMAKE_ASM<DIALECT>_FLAGS <CMAKE_<LANG>_FLAGS>`` variable is defined. +Add default compilation flags to be used when compiling a specific dialect +of an assembly language. ``ASM<DIALECT>FLAGS`` can be one of: + +* ``ASMFLAGS`` +* ``ASM_NASMFLAGS`` +* ``ASM_MASMFLAGS`` +* ``ASM-ATTFLAGS`` + +.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_ASM<DIALECT>_FLAGS <CMAKE_<LANG>_FLAGS>` +.. |LANG| replace:: ``ASM<DIALECT>`` +.. include:: LANG_FLAGS.txt See also :variable:`CMAKE_ASM<DIALECT>_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`. diff --git a/Help/envvar/CFLAGS.rst b/Help/envvar/CFLAGS.rst index 190b4f4..a6b2452 100644 --- a/Help/envvar/CFLAGS.rst +++ b/Help/envvar/CFLAGS.rst @@ -3,11 +3,10 @@ CFLAGS .. include:: ENV_VAR.txt -Default compilation flags to be used when compiling ``C`` files. Will only be -used by CMake on the first configuration to determine ``CC`` default compilation -flags, after which the value for ``CFLAGS`` is stored in the cache -as :variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration run -(including the first), the environment variable will be ignored if the -:variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined. +Add default compilation flags to be used when compiling ``C`` files. + +.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_C_FLAGS <CMAKE_<LANG>_FLAGS>` +.. |LANG| replace:: ``C`` +.. include:: LANG_FLAGS.txt See also :variable:`CMAKE_C_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`. diff --git a/Help/envvar/CMAKE_GENERATOR.rst b/Help/envvar/CMAKE_GENERATOR.rst index 3488b04..596e8f3 100644 --- a/Help/envvar/CMAKE_GENERATOR.rst +++ b/Help/envvar/CMAKE_GENERATOR.rst @@ -6,9 +6,9 @@ CMAKE_GENERATOR .. include:: ENV_VAR.txt Specifies the CMake default generator to use when no generator is supplied -with ``-G``. If the provided value doesn't name a generator known by CMake, -the internal default is used. Either way the resulting generator selection -is stored in the :variable:`CMAKE_GENERATOR` variable. +with :option:`-G <cmake -G>`. If the provided value doesn't name a generator +known by CMake, the internal default is used. Either way the resulting +generator selection is stored in the :variable:`CMAKE_GENERATOR` variable. Some generators may be additionally configured using the environment variables: diff --git a/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst b/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst index b039845..e657904 100644 --- a/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst +++ b/Help/envvar/CMAKE_GENERATOR_PLATFORM.rst @@ -6,5 +6,5 @@ CMAKE_GENERATOR_PLATFORM .. include:: ENV_VAR.txt Default value for :variable:`CMAKE_GENERATOR_PLATFORM` if no Cache entry -is present and no value is specified by :manual:`cmake(1)` ``-A`` option. +is present and no value is specified by :option:`cmake -A` option. This value is only applied if :envvar:`CMAKE_GENERATOR` is set. diff --git a/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst b/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst index 394dd88..03208e7 100644 --- a/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst +++ b/Help/envvar/CMAKE_GENERATOR_TOOLSET.rst @@ -6,5 +6,5 @@ CMAKE_GENERATOR_TOOLSET .. include:: ENV_VAR.txt Default value for :variable:`CMAKE_GENERATOR_TOOLSET` if no Cache entry -is present and no value is specified by :manual:`cmake(1)` ``-T`` option. +is present and no value is specified by :option:`cmake -T` option. This value is only applied if :envvar:`CMAKE_GENERATOR` is set. diff --git a/Help/envvar/CSFLAGS.rst b/Help/envvar/CSFLAGS.rst index 784328a..6e909fe 100644 --- a/Help/envvar/CSFLAGS.rst +++ b/Help/envvar/CSFLAGS.rst @@ -5,11 +5,10 @@ CSFLAGS .. include:: ENV_VAR.txt -Default compilation flags to be used when compiling ``CSharp`` files. Will only be -used by CMake on the first configuration to determine ``CSharp`` default -compilation flags, after which the value for ``CSFLAGS`` is stored in the cache -as :variable:`CMAKE_CSharp_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration -run (including the first), the environment variable will be ignored if the -:variable:`CMAKE_CSharp_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined. +Add default compilation flags to be used when compiling ``CSharp`` files. + +.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_CSharp_FLAGS <CMAKE_<LANG>_FLAGS>` +.. |LANG| replace:: ``CSharp`` +.. include:: LANG_FLAGS.txt See also :variable:`CMAKE_CSharp_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`. diff --git a/Help/envvar/CTEST_PROGRESS_OUTPUT.rst b/Help/envvar/CTEST_PROGRESS_OUTPUT.rst index 8c29d7d..348acc6 100644 --- a/Help/envvar/CTEST_PROGRESS_OUTPUT.rst +++ b/Help/envvar/CTEST_PROGRESS_OUTPUT.rst @@ -14,5 +14,5 @@ variable is not set or has a value that evaluates to false, output is reported normally with each test having its own start and end lines logged to the output. -The ``--progress`` option to :manual:`ctest <ctest(1)>` overrides this -environment variable if both are given. +The :option:`--progress <ctest --progress>` option to :manual:`ctest <ctest(1)>` +overrides this environment variable if both are given. diff --git a/Help/envvar/CUDAFLAGS.rst b/Help/envvar/CUDAFLAGS.rst index af577a0..46a91df 100644 --- a/Help/envvar/CUDAFLAGS.rst +++ b/Help/envvar/CUDAFLAGS.rst @@ -5,11 +5,10 @@ CUDAFLAGS .. include:: ENV_VAR.txt -Default compilation flags to be used when compiling ``CUDA`` files. Will only be -used by CMake on the first configuration to determine ``CUDA`` default -compilation flags, after which the value for ``CUDAFLAGS`` is stored in the -cache as :variable:`CMAKE_CUDA_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration -run (including the first), the environment variable will be ignored if -the :variable:`CMAKE_CUDA_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined. +Add default compilation flags to be used when compiling ``CUDA`` files. + +.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_CUDA_FLAGS <CMAKE_<LANG>_FLAGS>` +.. |LANG| replace:: ``CUDA`` +.. include:: LANG_FLAGS.txt See also :variable:`CMAKE_CUDA_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`. diff --git a/Help/envvar/CXXFLAGS.rst b/Help/envvar/CXXFLAGS.rst index 460a347..f67431f 100644 --- a/Help/envvar/CXXFLAGS.rst +++ b/Help/envvar/CXXFLAGS.rst @@ -3,11 +3,10 @@ CXXFLAGS .. include:: ENV_VAR.txt -Default compilation flags to be used when compiling ``CXX`` (C++) files. Will -only be used by CMake on the first configuration to determine ``CXX`` default -compilation flags, after which the value for ``CXXFLAGS`` is stored in the cache -as :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration run ( -including the first), the environment variable will be ignored if -the :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined. +Add default compilation flags to be used when compiling ``CXX`` (C++) files. + +.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_CXX_FLAGS <CMAKE_<LANG>_FLAGS>` +.. |LANG| replace:: ``CXX`` +.. include:: LANG_FLAGS.txt See also :variable:`CMAKE_CXX_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`. diff --git a/Help/envvar/DESTDIR.rst b/Help/envvar/DESTDIR.rst index 94cae4a..dec8430 100644 --- a/Help/envvar/DESTDIR.rst +++ b/Help/envvar/DESTDIR.rst @@ -20,8 +20,9 @@ The packaging tool may then construct the package from the content of the See the :variable:`CMAKE_INSTALL_PREFIX` variable to control the installation prefix when configuring a build tree. Or, when using -the :manual:`cmake(1)` command-line tool's ``--install`` mode, -one may specify a different prefix using the ``--prefix`` option. +the :manual:`cmake(1)` command-line tool's :option:`--install <cmake --install>` +mode, one may specify a different prefix using the +:option:`--prefix <cmake--install --prefix>` option. .. note:: diff --git a/Help/envvar/FFLAGS.rst b/Help/envvar/FFLAGS.rst index 53bffb6..23bc8d2 100644 --- a/Help/envvar/FFLAGS.rst +++ b/Help/envvar/FFLAGS.rst @@ -3,11 +3,10 @@ FFLAGS .. include:: ENV_VAR.txt -Default compilation flags to be used when compiling ``Fortran`` files. Will only -be used by CMake on the first configuration to determine ``Fortran`` default -compilation flags, after which the value for ``FFLAGS`` is stored in the cache -as :variable:`CMAKE_Fortran_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration -run (including the first), the environment variable will be ignored if -the :variable:`CMAKE_Fortran_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined. +Add default compilation flags to be used when compiling ``Fortran`` files. + +.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_Fortran_FLAGS <CMAKE_<LANG>_FLAGS>` +.. |LANG| replace:: ``Fortran`` +.. include:: LANG_FLAGS.txt See also :variable:`CMAKE_Fortran_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`. diff --git a/Help/envvar/HIPFLAGS.rst b/Help/envvar/HIPFLAGS.rst index 0df3416..31e2390 100644 --- a/Help/envvar/HIPFLAGS.rst +++ b/Help/envvar/HIPFLAGS.rst @@ -5,11 +5,10 @@ HIPFLAGS .. include:: ENV_VAR.txt -Default compilation flags to be used when compiling ``HIP`` files. Will only be -used by CMake on the first configuration to determine ``HIP`` default -compilation flags, after which the value for ``HIPFLAGS`` is stored in the -cache as :variable:`CMAKE_HIP_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration -run (including the first), the environment variable will be ignored if -the :variable:`CMAKE_HIP_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined. +Add default compilation flags to be used when compiling ``HIP`` files. + +.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_HIP_FLAGS <CMAKE_<LANG>_FLAGS>` +.. |LANG| replace:: ``HIP`` +.. include:: LANG_FLAGS.txt See also :variable:`CMAKE_HIP_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`. diff --git a/Help/envvar/ISPCFLAGS.rst b/Help/envvar/ISPCFLAGS.rst index 21df037..b7a2bd5 100644 --- a/Help/envvar/ISPCFLAGS.rst +++ b/Help/envvar/ISPCFLAGS.rst @@ -5,11 +5,10 @@ ISPCFLAGS .. include:: ENV_VAR.txt -Default compilation flags to be used when compiling ``ISPC`` files. Will only be -used by CMake on the first configuration to determine ``ISPC`` default -compilation flags, after which the value for ``ISPCFLAGS`` is stored in the -cache as :variable:`CMAKE_ISPC_FLAGS <CMAKE_<LANG>_FLAGS>`. For any configuration -run (including the first), the environment variable will be ignored if -the :variable:`CMAKE_ISPC_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined. +Add default compilation flags to be used when compiling ``ISPC`` files. + +.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_ISPC_FLAGS <CMAKE_<LANG>_FLAGS>` +.. |LANG| replace:: ``ISPC`` +.. include:: LANG_FLAGS.txt See also :variable:`CMAKE_ISPC_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`. diff --git a/Help/envvar/LANG_FLAGS.txt b/Help/envvar/LANG_FLAGS.txt new file mode 100644 index 0000000..d01a56d --- /dev/null +++ b/Help/envvar/LANG_FLAGS.txt @@ -0,0 +1,6 @@ +CMake uses this environment variable value, in combination with its own +builtin default flags for the toolchain, to initialize and store the +|CMAKE_LANG_FLAGS| cache entry. +This occurs the first time a build tree is configured for language |LANG|. +For any configuration run (including the first), the environment variable +will be ignored if the |CMAKE_LANG_FLAGS| variable is already defined. diff --git a/Help/envvar/RCFLAGS.rst b/Help/envvar/RCFLAGS.rst index bc43cb2..7df83a7 100644 --- a/Help/envvar/RCFLAGS.rst +++ b/Help/envvar/RCFLAGS.rst @@ -3,11 +3,10 @@ RCFLAGS .. include:: ENV_VAR.txt -Default compilation flags to be used when compiling ``resource`` files. Will -only be used by CMake on the first configuration to determine ``resource`` -default compilation flags, after which the value for ``RCFLAGS`` is stored in -the cache as :variable:`CMAKE_RC_FLAGS <CMAKE_<LANG>_FLAGS>`. For any -configuration run (including the first), the environment variable will be ignored -if the :variable:`CMAKE_RC_FLAGS <CMAKE_<LANG>_FLAGS>` variable is defined. +Add default compilation flags to be used when compiling ``RC`` (resource) files. + +.. |CMAKE_LANG_FLAGS| replace:: :variable:`CMAKE_RC_FLAGS <CMAKE_<LANG>_FLAGS>` +.. |LANG| replace:: ``RC`` +.. include:: LANG_FLAGS.txt See also :variable:`CMAKE_RC_FLAGS_INIT <CMAKE_<LANG>_FLAGS_INIT>`. diff --git a/Help/envvar/SSL_CERT_DIR.rst b/Help/envvar/SSL_CERT_DIR.rst new file mode 100644 index 0000000..1e678e4 --- /dev/null +++ b/Help/envvar/SSL_CERT_DIR.rst @@ -0,0 +1,9 @@ +SSL_CERT_DIR +------------ + +.. versionadded:: 3.25 + +.. include:: ENV_VAR.txt + +Specify default directory containing CA certificates. It overrides +the default CA directory used. diff --git a/Help/envvar/SSL_CERT_FILE.rst b/Help/envvar/SSL_CERT_FILE.rst new file mode 100644 index 0000000..23216c0 --- /dev/null +++ b/Help/envvar/SSL_CERT_FILE.rst @@ -0,0 +1,9 @@ +SSL_CERT_FILE +------------- + +.. versionadded:: 3.25 + +.. include:: ENV_VAR.txt + +Specify the file name containing CA certificates. It overrides the +default, os-specific CA file used. diff --git a/Help/generator/Green Hills MULTI.rst b/Help/generator/Green Hills MULTI.rst index 1b4739b..7a5993a 100644 --- a/Help/generator/Green Hills MULTI.rst +++ b/Help/generator/Green Hills MULTI.rst @@ -28,12 +28,12 @@ Otherwise the ``primaryTarget`` will be composed from the values of :variable:`C and ``GHS_TARGET_PLATFORM``. Defaulting to the value of ``arm_integrity.tgt`` * The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps - via the :manual:`cmake(1)` ``-A`` option. + via the :option:`cmake -A` option. | Typical values of ``arm``, ``ppc``, ``86``, etcetera, are used. -* The variable ``GHS_TARGET_PLATFORM`` may be set, perhaps via the :manual:`cmake(1)` - ``-D`` option. +* The variable ``GHS_TARGET_PLATFORM`` may be set, perhaps via the :option:`cmake -D` + option. | Defaults to ``integrity``. | Usual values are ``integrity``, ``threadx``, ``uvelosity``, ``velosity``, @@ -55,11 +55,11 @@ The generator searches for the latest compiler or can be given a location to use ``GHS_TOOLSET_ROOT`` is the directory that is checked for the latest compiler. * The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps - via the :manual:`cmake(1)` ``-T`` option, to specify the location of the toolset. + via the :option:`cmake -T` option, to specify the location of the toolset. Both absolute and relative paths are valid. Paths are relative to ``GHS_TOOLSET_ROOT``. -* The variable ``GHS_TOOLSET_ROOT`` may be set, perhaps via the :manual:`cmake(1)` - ``-D`` option. +* The variable ``GHS_TOOLSET_ROOT`` may be set, perhaps via the :option:`cmake -D` + option. | Root path for toolset searches and relative paths. | Defaults to ``C:/ghs`` in Windows or ``/usr/ghs`` in Linux. diff --git a/Help/generator/Ninja Multi-Config.rst b/Help/generator/Ninja Multi-Config.rst index e5ce4f5..2cf823a 100644 --- a/Help/generator/Ninja Multi-Config.rst +++ b/Help/generator/Ninja Multi-Config.rst @@ -20,8 +20,8 @@ are intended to be run with ``ninja -f build-<Config>.ninja``. A :variable:`CMAKE_CONFIGURATION_TYPES`. ``cmake --build . --config <Config>`` will always use ``build-<Config>.ninja`` -to build. If no ``--config`` argument is specified, ``cmake --build .`` will -use ``build.ninja``. +to build. If no :option:`--config <cmake--build --config>` argument is +specified, :option:`cmake --build . <cmake --build>` will use ``build.ninja``. Each ``build-<Config>.ninja`` file contains ``<target>`` targets as well as ``<target>:<Config>`` targets, where ``<Config>`` is the same as the diff --git a/Help/generator/Visual Studio 10 2010.rst b/Help/generator/Visual Studio 10 2010.rst index 9ec33c3..888164f 100644 --- a/Help/generator/Visual Studio 10 2010.rst +++ b/Help/generator/Visual Studio 10 2010.rst @@ -1,52 +1,8 @@ Visual Studio 10 2010 --------------------- -Deprecated. Generates Visual Studio 10 (VS 2010) project files. - -.. note:: - This generator is deprecated and will be removed in a future version - of CMake. It will still be possible to build with VS 10 2010 tools - using the :generator:`Visual Studio 11 2012` (or above) generator - with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v100``, or by - using the :generator:`NMake Makefiles` generator. - -For compatibility with CMake versions prior to 3.0, one may specify this -generator using the name ``Visual Studio 10`` without the year component. - -Project Types -^^^^^^^^^^^^^ - -Only Visual C++ and C# projects may be generated (and Fortran with -Intel compiler integration). Other types of projects (Database, -Website, etc.) are not supported. - -Platform Selection -^^^^^^^^^^^^^^^^^^ - -The default target platform name (architecture) is ``Win32``. - -.. versionadded:: 3.1 - The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps - via the :manual:`cmake(1)` ``-A`` option, to specify a target platform - name (architecture). For example: - - * ``cmake -G "Visual Studio 10 2010" -A Win32`` - * ``cmake -G "Visual Studio 10 2010" -A x64`` - * ``cmake -G "Visual Studio 10 2010" -A Itanium`` - -For compatibility with CMake versions prior to 3.1, one may specify -a target platform name optionally at the end of the generator name. -This is supported only for: - -``Visual Studio 10 2010 Win64`` - Specify target platform ``x64``. - -``Visual Studio 10 2010 IA64`` - Specify target platform ``Itanium``. - -Toolset Selection -^^^^^^^^^^^^^^^^^ - -The ``v100`` toolset that comes with Visual Studio 10 2010 is selected by -default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps -via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. +Removed. This once generated Visual Studio 10 2010 project files, but +the generator has been removed since CMake 3.25. It is still possible +to build with VS 10 2010 tools using the :generator:`Visual Studio 12 2013` +(or above) generator with :variable:`CMAKE_GENERATOR_TOOLSET` set to +``v100``, or by using the :generator:`NMake Makefiles` generator. diff --git a/Help/generator/Visual Studio 11 2012.rst b/Help/generator/Visual Studio 11 2012.rst index 3952228..4e7195c 100644 --- a/Help/generator/Visual Studio 11 2012.rst +++ b/Help/generator/Visual Studio 11 2012.rst @@ -1,7 +1,14 @@ Visual Studio 11 2012 --------------------- -Generates Visual Studio 11 (VS 2012) project files. +Deprecated. Generates Visual Studio 11 (VS 2012) project files. + +.. note:: + This generator is deprecated and will be removed in a future version + of CMake. It will still be possible to build with VS 11 2012 tools + using the :generator:`Visual Studio 12 2013` (or above) generator + with :variable:`CMAKE_GENERATOR_TOOLSET` set to ``v110``, or by + using the :generator:`NMake Makefiles` generator. For compatibility with CMake versions prior to 3.0, one may specify this generator using the name "Visual Studio 11" without the year component. @@ -20,7 +27,7 @@ The default target platform name (architecture) is ``Win32``. .. versionadded:: 3.1 The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps - via the :manual:`cmake(1)` ``-A`` option, to specify a target platform + via the :option:`cmake -A` option, to specify a target platform name (architecture). For example: * ``cmake -G "Visual Studio 11 2012" -A Win32`` @@ -47,4 +54,4 @@ Toolset Selection The ``v110`` toolset that comes with Visual Studio 11 2012 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps -via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. +via the :option:`cmake -T` option, to specify another toolset. diff --git a/Help/generator/Visual Studio 12 2013.rst b/Help/generator/Visual Studio 12 2013.rst index 54a4d7e..3dbcfe6 100644 --- a/Help/generator/Visual Studio 12 2013.rst +++ b/Help/generator/Visual Studio 12 2013.rst @@ -20,7 +20,7 @@ The default target platform name (architecture) is ``Win32``. .. versionadded:: 3.1 The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps - via the :manual:`cmake(1)` ``-A`` option, to specify a target platform + via the :option:`cmake -A` option, to specify a target platform name (architecture). For example: * ``cmake -G "Visual Studio 12 2013" -A Win32`` @@ -42,7 +42,7 @@ Toolset Selection The ``v120`` toolset that comes with Visual Studio 12 2013 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps -via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. +via the :option:`cmake -T` option, to specify another toolset. .. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: By default this generator uses the 32-bit variant even on a 64-bit host. diff --git a/Help/generator/Visual Studio 14 2015.rst b/Help/generator/Visual Studio 14 2015.rst index d704ab2..af7dfaa 100644 --- a/Help/generator/Visual Studio 14 2015.rst +++ b/Help/generator/Visual Studio 14 2015.rst @@ -18,7 +18,7 @@ Platform Selection The default target platform name (architecture) is ``Win32``. The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps -via the :manual:`cmake(1)` ``-A`` option, to specify a target platform +via the :option:`cmake -A` option, to specify a target platform name (architecture). For example: * ``cmake -G "Visual Studio 14 2015" -A Win32`` @@ -40,7 +40,7 @@ Toolset Selection The ``v140`` toolset that comes with Visual Studio 14 2015 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps -via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. +via the :option:`cmake -T` option, to specify another toolset. .. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: By default this generator uses the 32-bit variant even on a 64-bit host. diff --git a/Help/generator/Visual Studio 15 2017.rst b/Help/generator/Visual Studio 15 2017.rst index 912afad..6bcc033 100644 --- a/Help/generator/Visual Studio 15 2017.rst +++ b/Help/generator/Visual Studio 15 2017.rst @@ -26,7 +26,7 @@ Platform Selection The default target platform name (architecture) is ``Win32``. The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps -via the :manual:`cmake(1)` ``-A`` option, to specify a target platform +via the :option:`cmake -A` option, to specify a target platform name (architecture). For example: * ``cmake -G "Visual Studio 15 2017" -A Win32`` @@ -49,7 +49,7 @@ Toolset Selection The ``v141`` toolset that comes with Visual Studio 15 2017 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps -via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. +via the :option:`cmake -T` option, to specify another toolset. .. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: By default this generator uses the 32-bit variant even on a 64-bit host. diff --git a/Help/generator/Visual Studio 16 2019.rst b/Help/generator/Visual Studio 16 2019.rst index 6cefe6d..2918a6e 100644 --- a/Help/generator/Visual Studio 16 2019.rst +++ b/Help/generator/Visual Studio 16 2019.rst @@ -25,7 +25,7 @@ The default target platform name (architecture) is that of the host and is provided in the :variable:`CMAKE_VS_PLATFORM_NAME_DEFAULT` variable. The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps -via the :manual:`cmake(1)` ``-A`` option, to specify a target platform +via the :option:`cmake -A` option, to specify a target platform name (architecture). For example: * ``cmake -G "Visual Studio 16 2019" -A Win32`` @@ -38,7 +38,7 @@ Toolset Selection The ``v142`` toolset that comes with Visual Studio 16 2019 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps -via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. +via the :option:`cmake -T` option, to specify another toolset. .. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: By default this generator uses the 64-bit variant on x64 hosts and diff --git a/Help/generator/Visual Studio 17 2022.rst b/Help/generator/Visual Studio 17 2022.rst index edf9d60..ab101ac 100644 --- a/Help/generator/Visual Studio 17 2022.rst +++ b/Help/generator/Visual Studio 17 2022.rst @@ -25,7 +25,7 @@ The default target platform name (architecture) is that of the host and is provided in the :variable:`CMAKE_VS_PLATFORM_NAME_DEFAULT` variable. The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps -via the :manual:`cmake(1)` ``-A`` option, to specify a target platform +via the :option:`cmake -A` option, to specify a target platform name (architecture). For example: * ``cmake -G "Visual Studio 17 2022" -A Win32`` @@ -38,7 +38,7 @@ Toolset Selection The ``v143`` toolset that comes with VS 17 2022 is selected by default. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps -via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. +via the :option:`cmake -T` option, to specify another toolset. .. |VS_TOOLSET_HOST_ARCH_DEFAULT| replace:: By default this generator uses the 64-bit variant on x64 hosts and diff --git a/Help/generator/Visual Studio 9 2008.rst b/Help/generator/Visual Studio 9 2008.rst index 644f936..3434956 100644 --- a/Help/generator/Visual Studio 9 2008.rst +++ b/Help/generator/Visual Studio 9 2008.rst @@ -10,7 +10,7 @@ The default target platform name (architecture) is ``Win32``. .. versionadded:: 3.1 The :variable:`CMAKE_GENERATOR_PLATFORM` variable may be set, perhaps - via the :manual:`cmake(1)` ``-A`` option, to specify a target platform + via the :option:`cmake -A` option, to specify a target platform name (architecture). For example: * ``cmake -G "Visual Studio 9 2008" -A Win32`` diff --git a/Help/generator/Xcode.rst b/Help/generator/Xcode.rst index e4900a1..9dd5015 100644 --- a/Help/generator/Xcode.rst +++ b/Help/generator/Xcode.rst @@ -13,7 +13,7 @@ Toolset and Build System Selection By default Xcode is allowed to select its own default toolchain. The :variable:`CMAKE_GENERATOR_TOOLSET` option may be set, perhaps -via the :manual:`cmake(1)` ``-T`` option, to specify another toolset. +via the :option:`cmake -T` option, to specify another toolset. .. versionadded:: 3.19 This generator supports toolset specification using one of these forms: @@ -34,7 +34,7 @@ Supported pairs are: See the :variable:`CMAKE_XCODE_BUILD_SYSTEM` variable for allowed values. For example, to select the original build system under Xcode 12, - run :manual:`cmake(1)` with the option ``-T buildsystem=1``. + run :manual:`cmake(1)` with the option :option:`-T buildsystem=1 <cmake -T>`. Swift Support ^^^^^^^^^^^^^ @@ -44,3 +44,13 @@ Swift Support When using the :generator:`Xcode` generator with Xcode 6.1 or higher, one may enable the ``Swift`` language with the :command:`enable_language` command or the :command:`project`. + +Limitations +^^^^^^^^^^^ + +The Xcode generator does not support per-configuration sources. +Code like the following will result in a generation error: + +.. code-block:: cmake + + add_executable(MyApp mymain-$<CONFIG>.cpp) diff --git a/Help/guide/ide-integration/index.rst b/Help/guide/ide-integration/index.rst index 8473481..e198789 100644 --- a/Help/guide/ide-integration/index.rst +++ b/Help/guide/ide-integration/index.rst @@ -47,8 +47,9 @@ does, and present the user with the presets listed in the file. Users should be able to see (and possibly edit) the CMake cache variables, environment variables, and command line options that are defined for a given preset. The IDE should then construct the list of appropriate :manual:`cmake(1)` command -line arguments based on these settings, rather than using the ``--preset=`` -option directly. The ``--preset=`` option is intended only as a convenient +line arguments based on these settings, rather than using the +:option:`--preset= <cmake --preset>` option directly. The +:option:`--preset= <cmake --preset>` option is intended only as a convenient frontend for command line users, and should not be used by the IDE. For example, if a preset named ``ninja`` specifies ``Ninja`` as the generator @@ -66,10 +67,9 @@ run: cmake -S /path/to/source -B /path/to/source/build -G Ninja In cases where a preset contains lots of cache variables, and passing all of -them as ``-D`` flags would cause the command line length limit of the platform -to be exceeded, the IDE should instead construct a temporary cache script and -pass it with the ``-C`` flag. See :ref:`CMake Options` for details on how the -``-C`` flag is used. +them as :option:`-D <cmake -D>` flags would cause the command line length limit +of the platform to be exceeded, the IDE should instead construct a temporary +cache script and pass it with the :option:`-C <cmake -C>` flag. While reading, parsing, and evaluating the contents of ``CMakePresets.json`` is straightforward, it is not trivial. In addition to the documentation, IDE @@ -110,8 +110,9 @@ Building If a Makefile or Ninja generator is used to generate the build tree, it is not recommended to invoke ``make`` or ``ninja`` directly. Instead, it is -recommended that the IDE invoke :manual:`cmake(1)` with the ``--build`` -argument, which will in turn invoke the appropriate build tool. +recommended that the IDE invoke :manual:`cmake(1)` with the +:option:`--build <cmake --build>` argument, which will in turn invoke the +appropriate build tool. If an IDE project generator is used, such as :generator:`Xcode` or one of the Visual Studio generators, and the IDE understands the project format used, the diff --git a/Help/guide/tutorial/A Basic Starting Point.rst b/Help/guide/tutorial/A Basic Starting Point.rst index cf1ec01..3dac68a 100644 --- a/Help/guide/tutorial/A Basic Starting Point.rst +++ b/Help/guide/tutorial/A Basic Starting Point.rst @@ -1,34 +1,81 @@ Step 1: A Basic Starting Point ============================== -The most basic project is an executable built from source code files. -For simple projects, a three line ``CMakeLists.txt`` file is all that is -required. This will be the starting point for our tutorial. Create a -``CMakeLists.txt`` file in the ``Step1`` directory that looks like: - -.. code-block:: cmake - :caption: CMakeLists.txt - :name: CMakeLists.txt-start - - cmake_minimum_required(VERSION 3.10) +Where do I start with CMake? This step will provide an introduction to some of +CMake's basic syntax, commands, and variables. As these concepts are +introduced, we will work through three exercises and create a simple CMake +project. + +Each exercise in this step will start with some background information. Then, a +goal and list of helpful resources are provided. Each file in the +``Files to Edit`` section is in the ``Step1`` directory and contains one or +more ``TODO`` comments. Each ``TODO`` represents a line or two of code to +change or add. The ``TODO`` s are intended to be completed in numerical order, +first complete ``TODO 1`` then ``TODO 2``, etc. The ``Getting Started`` +section will give some helpful hints and guide you through the exercise. Then +the ``Build and Run`` section will walk step-by-step through how to build and +test the exercise. Finally, at the end of each exercise the intended solution +is discussed. + +Also note that each step in the tutorial builds on the next. So, for example, +the starting code for ``Step2`` is the complete solution to ``Step1``. + +Exercise 1 - Building a Basic Project +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The most basic CMake project is an executable built from a single source code +file. For simple projects like this, a ``CMakeLists.txt`` file with three +commands is all that is required. + +**Note:** Although upper, lower and mixed case commands are supported by CMake, +lower case commands are preferred and will be used throughout the tutorial. + +Any project's top most CMakeLists.txt must start by specifying a minimum CMake +version using the :command:`cmake_minimum_required` command. This establishes +policy settings and ensures that the following CMake functions are run with a +compatible version of CMake. + +To start a project, we use the :command:`project` command to set the project +name. This call is required with every project and should be called soon after +:command:`cmake_minimum_required`. As we will see later, this command can +also be used to specify other project level information such as the language +or version number. + +Finally, the :command:`add_executable` command tells CMake to create an +executable using the specified source code files. + +Goal +---- + +Understand how to create a simple CMake project. + +Helpful Resources +----------------- + +* :command:`add_executable` +* :command:`cmake_minimum_required` +* :command:`project` + +Files to Edit +------------- - # set the project name - project(Tutorial) +* ``CMakeLists.txt`` - # add the executable - add_executable(Tutorial tutorial.cxx) +Getting Started +---------------- +The source code for ``tutorial.cxx`` is provided in the +``Help/guide/tutorial/Step1`` directory and can be used to compute the square +root of a number. This file does not need to be edited in this step. -Note that this example uses lower case commands in the ``CMakeLists.txt`` file. -Upper, lower, and mixed case commands are supported by CMake. The source -code for ``tutorial.cxx`` is provided in the ``Step1`` directory and can be -used to compute the square root of a number. +In the same directory is a ``CMakeLists.txt`` file which you will complete. +Start with ``TODO 1`` and work through ``TODO 3``. Build and Run ------------- -That's all that is needed - we can build and run our project now! First, run -the :manual:`cmake <cmake(1)>` executable or the +Once ``TODO 1`` through ``TODO 3`` have been completed, we are ready to build +and run our project! First, run the :manual:`cmake <cmake(1)>` executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it with your chosen build tool. @@ -40,8 +87,9 @@ build directory: mkdir Step1_build -Next, navigate to the build directory and run CMake to configure the project -and generate a native build system: +Next, navigate to that build directory and run +:manual:`cmake <cmake(1)>` to configure the project and generate a native build +system: .. code-block:: console @@ -62,114 +110,352 @@ Finally, try to use the newly built ``Tutorial`` with these commands: Tutorial 10 Tutorial +Solution +-------- -Adding a Version Number and Configured Header File --------------------------------------------------- +As mentioned above, a three line ``CMakeLists.txt`` is all that we need to get +up and running. The first line is to use :command:`cmake_minimum_required` to +set the CMake version as follows: -The first feature we will add is to provide our executable and project with a -version number. While we could do this exclusively in the source code, using -``CMakeLists.txt`` provides more flexibility. +.. raw:: html -First, modify the ``CMakeLists.txt`` file to use the :command:`project` command -to set the project name and version number. + <details><summary>TODO 1: Click to show/hide answer</summary> .. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-project-VERSION + :caption: TODO 1: CMakeLists.txt + :name: CMakeLists.txt-cmake_minimum_required :language: cmake - :end-before: # specify the C++ standard + :end-before: # set the project name and version -Then, configure a header file to pass the version number to the source -code: +.. raw:: html -.. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-configure_file - :language: cmake - :start-after: # to the source code - :end-before: # add the executable + </details> + +The next step to make a basic project is to use the :command:`project` +command as follows to set the project name: + +.. raw:: html + + <details><summary>TODO 2: Click to show/hide answer</summary> + +.. code-block:: cmake + :caption: TODO 2: CMakeLists.txt + :name: CMakeLists.txt-project + + project(Tutorial) + +.. raw:: html -Since the configured file will be written into the binary tree, we -must add that directory to the list of paths to search for include -files. Add the following lines to the end of the ``CMakeLists.txt`` file: + </details> + +The last command to call for a basic project is +:command:`add_executable`. We call it as follows: + +.. raw:: html + + <details><summary>TODO 3: Click to show/hide answer</summary> .. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-target_include_directories + :caption: TODO 3: CMakeLists.txt + :name: CMakeLists.txt-add_executable :language: cmake - :start-after: # so that we will find TutorialConfig.h + :start-after: # add the executable + :end-before: # TODO 9: -Using your favorite editor, create ``TutorialConfig.h.in`` in the source -directory with the following contents: +.. raw:: html -.. literalinclude:: Step2/TutorialConfig.h.in - :caption: TutorialConfig.h.in - :name: TutorialConfig.h.in - :language: c++ + </details> -When CMake configures this header file the values for -``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be -replaced. +Exercise 2 - Specifying the C++ Standard +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Next modify ``tutorial.cxx`` to include the configured header file, -``TutorialConfig.h``. +CMake has some special variables that are either created behind the scenes or +have meaning to CMake when set by project code. Many of these variables start +with ``CMAKE_``. Avoid this naming convention when creating variables for your +projects. Two of these special user settable variables are +:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`. +These may be used together to specify the C++ standard needed to build the +project. -Finally, let's print out the executable name and version number by updating -``tutorial.cxx`` as follows: +Goal +---- -.. literalinclude:: Step2/tutorial.cxx - :caption: tutorial.cxx - :name: tutorial.cxx-print-version - :language: c++ - :start-after: { - :end-before: // convert input to double +Add a feature that requires C++11. + +Helpful Resources +----------------- + +* :variable:`CMAKE_CXX_STANDARD` +* :variable:`CMAKE_CXX_STANDARD_REQUIRED` +* :command:`set` + +Files to Edit +------------- -Specify the C++ Standard -------------------------- +* ``CMakeLists.txt`` +* ``tutorial.cxx`` -Next let's add some C++11 features to our project by replacing ``atof`` with -``std::stod`` in ``tutorial.cxx``. At the same time, remove -``#include <cstdlib>``. +Getting Started +--------------- + +Continue editing files in the ``Step1`` directory. Start with ``TODO 4`` and +complete through ``TODO 6``. + +First, edit ``tutorial.cxx`` by adding a feature that requires C++11. Then +update ``CMakeLists.txt`` to require C++11. + +Build and Run +------------- + +Let's build our project again. Since we already created a build directory and +ran CMake for Exercise 1, we can skip to the build step: + +.. code-block:: console + + cd Step1_build + cmake --build . + +Now we can try to use the newly built ``Tutorial`` with same commands as +before: + +.. code-block:: console + + Tutorial 4294967296 + Tutorial 10 + Tutorial + +Solution +-------- + +We start by adding some C++11 features to our project by replacing +``atof`` with ``std::stod`` in ``tutorial.cxx``. This looks like +the following: + +.. raw:: html + + <details><summary>TODO 4: Click to show/hide answer</summary> .. literalinclude:: Step2/tutorial.cxx - :caption: tutorial.cxx + :caption: TODO 4: tutorial.cxx :name: tutorial.cxx-cxx11 :language: c++ :start-after: // convert input to double - :end-before: // calculate square root + :end-before: // TODO 12: + +.. raw:: html + + </details> + +To complete ``TODO 5``, simply remove ``#include <cstdlib>``. We will need to explicitly state in the CMake code that it should use the -correct flags. The easiest way to enable support for a specific C++ standard -in CMake is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this -tutorial, set the :variable:`CMAKE_CXX_STANDARD` variable in the -``CMakeLists.txt`` file to ``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED` -to ``True``. Make sure to add the ``CMAKE_CXX_STANDARD`` declarations above the -call to ``add_executable``. +correct flags. One way to enable support for a specific C++ standard in CMake +is by using the :variable:`CMAKE_CXX_STANDARD` variable. For this tutorial, set +the :variable:`CMAKE_CXX_STANDARD` variable in the ``CMakeLists.txt`` file to +``11`` and :variable:`CMAKE_CXX_STANDARD_REQUIRED` to ``True``. Make sure to +add the :variable:`CMAKE_CXX_STANDARD` declarations above the call to +:command:`add_executable`. + +.. raw:: html + + <details><summary>TODO 6: Click to show/hide answer</summary> .. literalinclude:: Step2/CMakeLists.txt - :caption: CMakeLists.txt + :caption: TODO 6: CMakeLists.txt :name: CMakeLists.txt-CXX_STANDARD :language: cmake - :end-before: # configure a header file to pass some of the CMake settings + :start-after: # specify the C++ standard + :end-before: # TODO 7: + +.. raw:: html -Rebuild -------- + </details> -Let's build our project again. We already created a build directory and ran -CMake, so we can skip to the build step: +Exercise 3 - Adding a Version Number and Configured Header File +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes it may be useful to have a variable that is defined in your +``CMakelists.txt`` file also be available in your source code. In this case, we +would like to print the project version. + +One way to accomplish this is by using a configured header file. We create an +input file with one or more variables to replace. These variables have special +syntax which looks like ``@VAR@``. +Then, we use the :command:`configure_file` command to copy the input file to a +given output file and replace these variables with the current value of ``VAR`` +in the ``CMakelists.txt`` file. + +While we could edit the version directly in the source code, using this +feature is preferred since it creates a single source of truth and avoids +duplication. + +Goal +---- + +Define and report the project's version number. + +Helpful Resources +----------------- + +* :variable:`<PROJECT-NAME>_VERSION_MAJOR` +* :variable:`<PROJECT-NAME>_VERSION_MINOR` +* :command:`configure_file` +* :command:`target_include_directories` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``tutorial.cxx`` + +Getting Started +--------------- + +Continue to edit files from ``Step1``. Start on ``TODO 7`` and complete through +``TODO 12``. In this exercise, we start by adding a project version number in +``CMakeLists.txt``. In that same file, use :command:`configure_file` to copy a +given input file to an output file and substitute some variable values in the +input file content. + +Next, create an input header file ``TutorialConfig.h.in`` defining version +numbers which will accept variables passed from :command:`configure_file`. + +Finally, update ``tutorial.cxx`` to print out its version number. + +Build and Run +------------- + +Let's build our project again. As before, we already created a build directory +and ran CMake so we can skip to the build step: .. code-block:: console cd Step1_build cmake --build . -Now we can try to use the newly built ``Tutorial`` with same commands as before: +Verify that the version number is now reported when running the executable +without any arguments. -.. code-block:: console +Solution +-------- - Tutorial 4294967296 - Tutorial 10 - Tutorial +In this exercise, we improve our executable by printing a version number. +While we could do this exclusively in the source code, using ``CMakeLists.txt`` +lets us maintain a single source of data for the version number. + +First, we modify the ``CMakeLists.txt`` file to use the +:command:`project` command to set both the project name and version number. +When the :command:`project` command is called, CMake defines +``Tutorial_VERSION_MAJOR`` and ``Tutorial_VERSION_MINOR`` behind the scenes. + +.. raw:: html + + <details><summary>TODO 7: Click to show/hide answer</summary> + +.. literalinclude:: Step2/CMakeLists.txt + :caption: TODO 7: CMakeLists.txt + :name: CMakeLists.txt-project-VERSION + :language: cmake + :start-after: # set the project name and version + :end-before: # specify the C++ standard + +.. raw:: html + + </details> + +Then we used :command:`configure_file` to copy the input file with the +specified CMake variables replaced: + +.. raw:: html + + <details><summary>TODO 8: Click to show/hide answer</summary> + +.. literalinclude:: Step2/CMakeLists.txt + :caption: TODO 8: CMakeLists.txt + :name: CMakeLists.txt-configure_file + :language: cmake + :start-after: # to the source code + :end-before: # TODO 8: + +.. raw:: html + + </details> + +Since the configured file will be written into the project binary +directory, we must add that directory to the list of paths to search for +include files. + +**Note:** Throughout this tutorial, we will refer to the project build and +the project binary directory interchangeably. These are the same and are not +meant to refer to a `bin/` directory. + +We used :command:`target_include_directories` to specify +where the executable target should look for include files. + +.. raw:: html + + <details><summary>TODO 9: Click to show/hide answer</summary> + +.. literalinclude:: Step2/CMakeLists.txt + :caption: TODO 9: CMakeLists.txt + :name: CMakeLists.txt-target_include_directories + :language: cmake + :start-after: # so that we will find TutorialConfig.h + +.. raw:: html + + </details> + +``TutorialConfig.h.in`` is the input header file to be configured. +When :command:`configure_file` is called from our ``CMakeLists.txt``, the +values for ``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will +be replaced with the corresponding version numbers from the project in +``TutorialConfig.h``. + +.. raw:: html + + <details><summary>TODO 10: Click to show/hide answer</summary> + +.. literalinclude:: Step2/TutorialConfig.h.in + :caption: TODO 10: TutorialConfig.h.in + :name: TutorialConfig.h.in + :language: c++ + :end-before: // TODO 13: + +.. raw:: html + + </details> + +Next, we need to modify ``tutorial.cxx`` to include the configured header file, +``TutorialConfig.h``. + +.. raw:: html + + <details><summary>TODO 11: Click to show/hide answer</summary> + +.. code-block:: c++ + :caption: TODO 11: tutorial.cxx + + #include "TutorialConfig.h" + +.. raw:: html + + </details> + +Finally, we print out the executable name and version number by updating +``tutorial.cxx`` as follows: + +.. raw:: html + + <details><summary>TODO 12: Click to show/hide answer</summary> + +.. literalinclude:: Step2/tutorial.cxx + :caption: TODO 12 : tutorial.cxx + :name: tutorial.cxx-print-version + :language: c++ + :start-after: { + :end-before: // convert input to double + +.. raw:: html -Check that the version number is now reported when running the executable without -any arguments. + </details> diff --git a/Help/guide/tutorial/Adding Export Configuration.rst b/Help/guide/tutorial/Adding Export Configuration.rst index 3bd6d64..eb14f42 100644 --- a/Help/guide/tutorial/Adding Export Configuration.rst +++ b/Help/guide/tutorial/Adding Export Configuration.rst @@ -21,7 +21,7 @@ in ``MathFunctions/CMakeLists.txt`` to look like: :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-install-TARGETS-EXPORT :language: cmake - :start-after: # install rules + :start-after: # install libs Now that we have ``MathFunctions`` being exported, we also need to explicitly install the generated ``MathFunctionsTargets.cmake`` file. This is done by diff --git a/Help/guide/tutorial/Adding Generator Expressions.rst b/Help/guide/tutorial/Adding Generator Expressions.rst index 7fcc97f..6f9714e 100644 --- a/Help/guide/tutorial/Adding Generator Expressions.rst +++ b/Help/guide/tutorial/Adding Generator Expressions.rst @@ -1,4 +1,4 @@ -Step 10: Adding Generator Expressions +Step 4: Adding Generator Expressions ===================================== :manual:`Generator expressions <cmake-generator-expressions(7)>` are evaluated @@ -27,58 +27,280 @@ expressions are the ``0`` and ``1`` expressions. A ``$<0:...>`` results in the empty string, and ``<1:...>`` results in the content of ``...``. They can also be nested. +Exercise 1 - Setting the C++ Standard with Interface Libraries +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Before we use :manual:`generator expressions <cmake-generator-expressions(7)>` +let's refactor our existing code to use an ``INTERFACE`` library. We will +use that library in the next step to demonstrate a common use for +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +Goal +---- + +Add an ``INTERFACE`` library target to specify the required C++ standard. + +Helpful Resources +----------------- + +* :command:`add_library` +* :command:`target_compile_features` +* :command:`target_link_libraries` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``MathFunctions/CMakeLists.txt`` + +Getting Started +--------------- + +In this exercise, we will refactor our code to use an ``INTERFACE`` library to +specify the C++ standard. + +The starting source code is provided in the ``Step4`` directory. In this +exercise, complete ``TODO 1`` through ``TODO 3``. + +Start by editing the top level ``CMakeLists.txt`` file. Construct an +``INTERFACE`` library target called ``tutorial_compiler_flags`` and +specify ``cxx_std_11`` as a target compiler feature. + +Modify ``CMakeLists.txt`` and ``MathFunctions/CMakeLists.txt`` so that all +targets have a :command:`target_link_libraries` call to +``tutorial_compiler_flags``. + +Build and Run +------------- + +Make a new directory called ``Step4_build``, run the :manual:`cmake <cmake(1)>` +executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project +and then build it with your chosen build tool or by using ``cmake --build .`` +from the build directory. + +Here's a refresher of what that looks like from the command line: + +.. code-block:: console + + mkdir Step4_build + cd Step4_build + cmake ../Step4 + cmake --build . + +Next, use the newly built ``Tutorial`` and verify that it is working as +expected. + +Solution +-------- + +Let's update our code from the previous step to use interface libraries +to set our C++ requirements. + +To start, we need to remove the two :command:`set` calls on the variables +:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_STANDARD_REQUIRED`. +The specific lines to remove are as follows: + +.. literalinclude:: Step4/CMakeLists.txt + :caption: CMakeLists.txt + :name: CMakeLists.txt-CXX_STANDARD-variable-remove + :language: cmake + :start-after: # specify the C++ standard + :end-before: # TODO 5: Create helper variables + +Next, we need to create an interface library, ``tutorial_compiler_flags``. And +then use :command:`target_compile_features` to add the compiler feature +``cxx_std_11``. + + +.. raw:: html + + <details><summary>TODO 1: Click to show/hide answer</summary> + +.. literalinclude:: Step5/CMakeLists.txt + :caption: TODO 1: CMakeLists.txt + :name: CMakeLists.txt-cxx_std-feature + :language: cmake + :start-after: # specify the C++ standard + :end-before: # add compiler warning flags just + +.. raw:: html + + </details> + +Finally, with our interface library set up, we need to link our +executable ``Target`` and our ``MathFunctions`` library to our new +``tutorial_compiler_flags`` library. Respectively, the code will look like +this: + +.. raw:: html + + <details><summary>TODO 2: Click to show/hide answer</summary> + +.. literalinclude:: Step5/CMakeLists.txt + :caption: TODO 2: CMakeLists.txt + :name: CMakeLists.txt-target_link_libraries-step4 + :language: cmake + :start-after: add_executable(Tutorial tutorial.cxx) + :end-before: # add the binary tree to the search path for include file + +.. raw:: html + + </details> + +and this: + +.. raw:: html + + <details><summary>TODO 3: Click to show/hide answer</summary> + +.. literalinclude:: Step5/MathFunctions/CMakeLists.txt + :caption: TODO 3: MathFunctions/CMakeLists.txt + :name: MathFunctions-CMakeLists.txt-target_link_libraries-step4 + :language: cmake + :start-after: # link our compiler flags interface library + :end-before: # TODO 1 + +.. raw:: html + + </details> + +With this, all of our code still requires C++ 11 to build. Notice +though that with this method, it gives us the ability to be specific about +which targets get specific requirements. In addition, we create a single +source of truth in our interface library. + +Exercise 2 - Adding Compiler Warning Flags with Generator Expressions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + A common usage of :manual:`generator expressions <cmake-generator-expressions(7)>` is to conditionally add compiler flags, such as those for language levels or warnings. A nice pattern is to associate this information to an ``INTERFACE`` -target allowing this information to propagate. Let's start by constructing an -``INTERFACE`` target and specifying the required C++ standard level of ``11`` -instead of using :variable:`CMAKE_CXX_STANDARD`. +target allowing this information to propagate. -So the following code: +Goal +---- -.. literalinclude:: Step10/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-CXX_STANDARD-variable-remove +Add compiler warning flags when building but not for installed versions. + +Helpful Resources +----------------- + +* :manual:`cmake-generator-expressions(7)` +* :command:`cmake_minimum_required` +* :command:`set` +* :command:`target_compile_options` + +Files to Edit +------------- + +* ``CMakeLists.txt`` + +Getting Started +--------------- + +Start with the resulting files from Exercise 1. Complete ``TODO 4`` through +``TODO 7``. + +First, in the top level ``CMakeLists.txt`` file, we need to set the +:command:`cmake_minimum_required` to ``3.15``. In this exercise we are going +to use a generator expression which was introduced in CMake 3.15. + +Next we add the desired compiler warning flags that we want for our project. +As warning flags vary based on the compiler, we use the +``COMPILE_LANG_AND_ID`` generator expression to control which flags to apply +given a language and a set of compiler ids. + +Build and Run +------------- + +Since we have our build directory already configured from Exercise 1, simply +rebuild our code by calling the following: + +.. code-block:: console + + cd Step4_build + cmake --build . + +Solution +-------- + +Update the :command:`cmake_minimum_required` to require at least CMake +version ``3.15``: + +.. raw:: html + + <details><summary>TODO 4: Click to show/hide answer</summary> + +.. literalinclude:: Step5/CMakeLists.txt + :caption: TODO 4: CMakeLists.txt + :name: MathFunctions-CMakeLists.txt-minimum-required-step4 :language: cmake - :start-after: project(Tutorial VERSION 1.0) - :end-before: # control where the static and shared libraries are built so that on windows + :end-before: # set the project name and version -Would be replaced with: +.. raw:: html -.. literalinclude:: Step11/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-cxx_std-feature + </details> + +Next we determine which compiler our system is currently using to build +since warning flags vary based on the compiler we use. This is done with +the ``COMPILE_LANG_AND_ID`` generator expression. We set the result in the +variables ``gcc_like_cxx`` and ``msvc_cxx`` as follows: + +.. raw:: html + + <details><summary>TODO 5: Click to show/hide answer</summary> + +.. literalinclude:: Step5/CMakeLists.txt + :caption: TODO 5: CMakeLists.txt + :name: CMakeLists.txt-compile_lang_and_id :language: cmake - :start-after: project(Tutorial VERSION 1.0) - :end-before: # add compiler warning flags just when building this project via + :start-after: # the BUILD_INTERFACE genex + :end-before: target_compile_options(tutorial_compiler_flags INTERFACE -**Note**: This upcoming section will require a change to the -:command:`cmake_minimum_required` usage in the code. The Generator Expression -that is about to be used was introduced in `3.15`. Update the call to require -that more recent version: +.. raw:: html + + </details> + +Next we add the desired compiler warning flags that we want for our project. +Using our variables ``gcc_like_cxx`` and ``msvc_cxx``, we can use another +generator expression to apply the respective flags only when the variables are +true. We use :command:`target_compile_options` to apply these flags to our +interface library. + +.. raw:: html + + <details><summary>TODO 6: Click to show/hide answer</summary> .. code-block:: cmake - :caption: CMakeLists.txt - :name: CMakeLists.txt-version-update + :caption: TODO 6: CMakeLists.txt + :name: CMakeLists.txt-compile_flags - cmake_minimum_required(VERSION 3.15) + target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>" + "$<${msvc_cxx}:-W3>" + ) -Next we add the desired compiler warning flags that we want for our project. As -warning flags vary based on the compiler we use the ``COMPILE_LANG_AND_ID`` -generator expression to control which flags to apply given a language and a set -of compiler ids as seen below: +.. raw:: html -.. literalinclude:: Step11/CMakeLists.txt - :caption: CMakeLists.txt + </details> + +Lastly, we only want these warning flags to be used during builds. Consumers +of our installed project should not inherit our warning flags. To specify +this, we wrap our flags in a generator expression using the ``BUILD_INTERFACE`` +condition. The resulting full code looks like the following: + +.. raw:: html + + <details><summary>TODO 7: Click to show/hide answer</summary> + +.. literalinclude:: Step5/CMakeLists.txt + :caption: TODO 7: CMakeLists.txt :name: CMakeLists.txt-target_compile_options-genex :language: cmake - :start-after: # the BUILD_INTERFACE genex - :end-before: # control where the static and shared libraries are built so that on windows + :start-after: set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") + :end-before: # should we use our own math functions -Looking at this we see that the warning flags are encapsulated inside a -``BUILD_INTERFACE`` condition. This is done so that consumers of our installed -project will not inherit our warning flags. +.. raw:: html -**Exercise**: Modify ``MathFunctions/CMakeLists.txt`` so that all targets have -a :command:`target_link_libraries` call to ``tutorial_compiler_flags``. + </details> diff --git a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst index c6e0fd0..45d5976 100644 --- a/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst +++ b/Help/guide/tutorial/Adding Support for a Testing Dashboard.rst @@ -1,4 +1,4 @@ -Step 8: Adding Support for a Testing Dashboard +Step 6: Adding Support for a Testing Dashboard ============================================== Adding support for submitting our test results to a dashboard is simple. We @@ -9,21 +9,21 @@ we include the :module:`CTest` module in our top-level ``CMakeLists.txt``. Replace: -.. code-block:: cmake +.. literalinclude:: Step6/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-enable_testing-remove - - # enable testing - enable_testing() + :language: cmake + :start-after: # enable testing + :end-before: # does the application run With: -.. code-block:: cmake +.. literalinclude:: Step7/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-include-CTest - - # enable dashboard scripting - include(CTest) + :language: cmake + :start-after: # enable testing + :end-before: # does the application run The :module:`CTest` module will automatically call ``enable_testing()``, so we can remove it from our CMake files. @@ -46,7 +46,7 @@ downloaded from the ``Settings`` page of the project on the CDash instance that will host and display the test results. Once downloaded from CDash, the file should not be modified locally. -.. literalinclude:: Step9/CTestConfig.cmake +.. literalinclude:: Step7/CTestConfig.cmake :caption: CTestConfig.cmake :name: CTestConfig.cmake :language: cmake diff --git a/Help/guide/tutorial/Adding System Introspection.rst b/Help/guide/tutorial/Adding System Introspection.rst index 8db0cb8..ba91df4 100644 --- a/Help/guide/tutorial/Adding System Introspection.rst +++ b/Help/guide/tutorial/Adding System Introspection.rst @@ -1,4 +1,4 @@ -Step 5: Adding System Introspection +Step 7: Adding System Introspection =================================== Let us consider adding some code to our project that depends on features the @@ -15,7 +15,7 @@ these functions using the :module:`CheckCXXSourceCompiles` module in Add the checks for ``log`` and ``exp`` to ``MathFunctions/CMakeLists.txt``, after the call to :command:`target_include_directories`: -.. literalinclude:: Step6/MathFunctions/CMakeLists.txt +.. literalinclude:: Step8/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-check_cxx_source_compiles :language: cmake @@ -25,19 +25,19 @@ after the call to :command:`target_include_directories`: If available, use :command:`target_compile_definitions` to specify ``HAVE_LOG`` and ``HAVE_EXP`` as ``PRIVATE`` compile definitions. -.. literalinclude:: Step6/MathFunctions/CMakeLists.txt +.. literalinclude:: Step8/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-target_compile_definitions :language: cmake :start-after: # add compile definitions - :end-before: # install rules + :end-before: # install libs If ``log`` and ``exp`` are available on the system, then we will use them to compute the square root in the ``mysqrt`` function. Add the following code to the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the ``#endif`` before returning the result!): -.. literalinclude:: Step6/MathFunctions/mysqrt.cxx +.. literalinclude:: Step8/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx :name: MathFunctions/mysqrt.cxx-ifdef :language: c++ @@ -46,7 +46,7 @@ the ``mysqrt`` function in ``MathFunctions/mysqrt.cxx`` (don't forget the We will also need to modify ``mysqrt.cxx`` to include ``cmath``. -.. literalinclude:: Step6/MathFunctions/mysqrt.cxx +.. literalinclude:: Step8/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx :name: MathFunctions/mysqrt.cxx-include-cmath :language: c++ 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 a8e914e..4aef050 100644 --- a/Help/guide/tutorial/Adding Usage Requirements for a Library.rst +++ b/Help/guide/tutorial/Adding Usage Requirements for a Library.rst @@ -1,52 +1,147 @@ Step 3: Adding Usage Requirements for a Library =============================================== -Usage requirements allow for far better control over a library or executable's -link and include line while also giving more control over the transitive -property of targets inside CMake. The primary commands that leverage usage -requirements are: - - - :command:`target_compile_definitions` - - :command:`target_compile_options` - - :command:`target_include_directories` - - :command:`target_link_libraries` - -Let's refactor our code from :guide:`tutorial/Adding a Library` to use the -modern CMake approach of usage requirements. We first state that anybody -linking to ``MathFunctions`` needs to include the current source directory, -while ``MathFunctions`` itself doesn't. So this can become an ``INTERFACE`` -usage requirement. - -Remember ``INTERFACE`` means things that consumers require but the producer -doesn't. Add the following lines to the end of -``MathFunctions/CMakeLists.txt``: +Exercise 1 - Adding Usage Requirements for a Library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:ref:`Usage requirements <Target Usage Requirements>` of a target parameters +allow for far better control over a library or executable's link and include +line while also giving more control over the transitive property of targets +inside CMake. The primary commands that +leverage usage requirements are: + +* :command:`target_compile_definitions` +* :command:`target_compile_options` +* :command:`target_include_directories` +* :command:`target_link_directories` +* :command:`target_link_options` +* :command:`target_precompile_headers` +* :command:`target_sources` + + +Goal +---- + +Add usage requirements for a library. + +Helpful Materials +----------------- + +* :variable:`CMAKE_CURRENT_SOURCE_DIR` + +Files to Edit +------------- + +* ``MathFunctions/CMakeLists.txt`` +* ``CMakeLists.txt`` + +Getting Started +--------------- + +In this exercise, we will refactor our code from +:guide:`tutorial/Adding a Library` to use the modern CMake approach. We will +let our library define its own usage requirements so they are passed +transitively to other targets as necessary. In this case, ``MathFunctions`` +will specify any needed include directories itself. Then, the consuming target +``Tutorial`` simply needs to link to ``MathFunctions`` and not worry about +any additional include directories. + +The starting source code is provided in the ``Step3`` directory. In this +exercise, complete ``TODO 1`` through ``TODO 3``. + +First, add a call to :command:`target_include_directories` in +``MathFunctions/CMakeLists``. Remember that +:variable:`CMAKE_CURRENT_SOURCE_DIR` is the path to the source directory +currently being processed. + +Then, update (and simplify!) the call to +:command:`target_include_directories` in the top-level ``CMakeLists.txt``. + +Build and Run +------------- + +Make a new directory called ``Step3_build``, run the :manual:`cmake +<cmake(1)>` executable or the :manual:`cmake-gui <cmake-gui(1)>` to +configure the project and then build it with your chosen build tool or by +using :option:`cmake --build . <cmake --build>` from the build directory. +Here's a refresher of what that looks like from the command line: + +.. code-block:: console + + mkdir Step3_build + cd Step3_build + cmake ../Step3 + cmake --build . + +Next, use the newly built ``Tutorial`` and verify that it is working as +expected. + +Solution +-------- + +Let's update the code from the previous step to use the modern CMake +approach of usage requirements. + +We want to state that anybody linking to ``MathFunctions`` needs to include +the current source directory, while ``MathFunctions`` itself doesn't. This +can be expressed with an ``INTERFACE`` usage requirement. Remember +``INTERFACE`` means things that consumers require but the producer doesn't. + +At the end of ``MathFunctions/CMakeLists.txt``, use +:command:`target_include_directories` with the ``INTERFACE`` keyword, as +follows: + +.. raw:: html + + <details><summary>TODO 1: Click to show/hide answer</summary> .. literalinclude:: Step4/MathFunctions/CMakeLists.txt - :caption: MathFunctions/CMakeLists.txt + :caption: TODO 1: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-target_include_directories-INTERFACE :language: cmake :start-after: # to find MathFunctions.h + :end-before: # TODO 3: Link to + +.. raw:: html + + </details> -Now that we've specified usage requirements for ``MathFunctions`` we can safely -remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level +Now that we've specified usage requirements for ``MathFunctions`` we can +safely remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level ``CMakeLists.txt``, here: +.. raw:: html + + <details><summary>TODO 2: Click to show/hide answer</summary> + .. literalinclude:: Step4/CMakeLists.txt - :caption: CMakeLists.txt + :caption: TODO 2: CMakeLists.txt :name: CMakeLists.txt-remove-EXTRA_INCLUDES :language: cmake :start-after: # add the MathFunctions library :end-before: # add the executable +.. raw:: html + + </details> + And here: +.. raw:: html + + <details><summary>TODO 3: Click to show/hide answer</summary> + .. literalinclude:: Step4/CMakeLists.txt - :caption: CMakeLists.txt + :caption: TODO 3: CMakeLists.txt :name: CMakeLists.txt-target_include_directories-remove-EXTRA_INCLUDES :language: cmake :start-after: # so that we will find TutorialConfig.h -Once this is done, run the :manual:`cmake <cmake(1)>` executable or the -:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it -with your chosen build tool or by using ``cmake --build .`` from the build -directory. +.. raw:: html + + </details> + +Notice that with this technique, the only thing our executable target does to +use our library is call :command:`target_link_libraries` with the name +of the library target. In larger projects, the classic method of specifying +library dependencies manually becomes very complicated very quickly. 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 70c6695..b1f9840 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 @@ -1,4 +1,4 @@ -Step 6: Adding a Custom Command and Generated File +Step 8: Adding a Custom Command and Generated File ================================================== Suppose, for the purpose of this tutorial, we decide that we never want to use @@ -26,7 +26,7 @@ accomplish this. First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for ``MakeTable`` is added as any other executable would be added. -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_executable-MakeTable :language: cmake @@ -36,7 +36,7 @@ First, at the top of ``MathFunctions/CMakeLists.txt``, the executable for Then we add a custom command that specifies how to produce ``Table.h`` by running MakeTable. -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_custom_command-Table.h :language: cmake @@ -47,7 +47,7 @@ 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 of sources for the library MathFunctions. -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_library-Table.h :language: cmake @@ -57,17 +57,17 @@ of sources for the library MathFunctions. 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``. -.. literalinclude:: Step7/MathFunctions/CMakeLists.txt +.. literalinclude:: Step9/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-target_include_directories-Table.h :language: cmake :start-after: # state that we depend on our bin - :end-before: # install rules + :end-before: # install libs 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: -.. literalinclude:: Step7/MathFunctions/mysqrt.cxx +.. literalinclude:: Step9/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx :name: MathFunctions/mysqrt.cxx :language: c++ diff --git a/Help/guide/tutorial/Adding a Library.rst b/Help/guide/tutorial/Adding a Library.rst index 71755be..46a8909 100644 --- a/Help/guide/tutorial/Adding a Library.rst +++ b/Help/guide/tutorial/Adding a Library.rst @@ -1,136 +1,458 @@ Step 2: Adding a Library ======================== -Now we will add a library to our project. This library will contain our own +At this point, we have seen how to create a basic project using CMake. In this +step, we will learn how to create and use a library in our project. We will +also see how to make the use of our library optional. + +Exercise 1 - Creating a Library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To add a library in CMake, use the :command:`add_library` command and specify +which source files should make up the library. + +Rather than placing all of the source files in one directory, we can organize +our project with one or more subdirectories. In this case, we will create a +subdirectory specifically for our library. Here, we can add a new +``CMakeLists.txt`` file and one or more source files. In the top level +``CMakeLists.txt`` file, we will use the :command:`add_subdirectory` command +to add the subdirectory to the build. + +Once the library is created, it is connected to our executable target with +:command:`target_include_directories` and :command:`target_link_libraries`. + +Goal +---- + +Add and use a library. + +Helpful Resources +----------------- + +* :command:`add_library` +* :command:`add_subdirectory` +* :command:`target_include_directories` +* :command:`target_link_libraries` +* :variable:`PROJECT_SOURCE_DIR` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``tutorial.cxx`` +* ``MathFunctions/CMakeLists.txt`` + +Getting Started +--------------- + +In this exercise, we will add a library to our project that contains our own implementation for computing the square root of a number. The executable can 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``. The source file has one -function called ``mysqrt`` that provides similar functionality to the -compiler's ``sqrt`` function. +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 +``mysqrt`` that provides similar functionality to the compiler's ``sqrt`` +function. + +From the ``Help/guide/tutorial/Step2`` directory, start with ``TODO 1`` and +complete through ``TODO 6``. + +First, fill in the one line ``CMakeLists.txt`` in the ``MathFunctions`` +subdirectory. + +Next, edit the top level ``CMakeLists.txt``. + +Finally, use the newly created ``MathFunctions`` library in ``tutorial.cxx`` + +Build and Run +------------- + +Run the :manual:`cmake <cmake(1)>` executable or the +:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it +with your chosen build tool. + +Below is a refresher of what that looks like from the command line: + +.. code-block:: console + + mkdir Step2_build + cd Step2_build + cmake ../Step2 + cmake --build . + +Try to use the newly built ``Tutorial`` and ensure that it is still +producing accurate square root values. + +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 +:command:`add_library`. This looks like the following line: -Add the following one line ``CMakeLists.txt`` file to the ``MathFunctions`` -directory: +.. raw:: html + + <details><summary>TODO 1: Click to show/hide answer</summary> .. literalinclude:: Step3/MathFunctions/CMakeLists.txt - :caption: MathFunctions/CMakeLists.txt - :name: MathFunctions/CMakeLists.txt + :caption: TODO 1: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-add_library :language: cmake + :end-before: # TODO 1 + +.. raw:: html + + </details> To make use of the new library we will add an :command:`add_subdirectory` call in the top-level ``CMakeLists.txt`` file so that the library will get -built. We add the new library to the executable, and add ``MathFunctions`` as -an include directory so that the ``MathFunctions.h`` header file can be found. -The last few lines of the top-level ``CMakeLists.txt`` file should now look -like: +built. + +.. raw:: html + + <details><summary>TODO 2: Click to show/hide answer</summary> + +.. code-block:: cmake + :caption: TODO 2: CMakeLists.txt + :name: CMakeLists.txt-add_subdirectory + + add_subdirectory(MathFunctions) + +.. raw:: html + + </details> + +Next, the new library target is linked to the executable target using +:command:`target_link_libraries`. + +.. raw:: html + + <details><summary>TODO 3: Click to show/hide answer</summary> + +.. code-block:: cmake + :caption: TODO 3: CMakeLists.txt + :name: CMakeLists.txt-target_link_libraries + + target_link_libraries(Tutorial PUBLIC MathFunctions) + +.. raw:: html + + </details> + +Finally we need to specify the library's header file location. Modify +:command:`target_include_directories` to add the ``MathFunctions`` subdirectory +as an include directory so that the ``MathFunctions.h`` header file can be +found. + +.. raw:: html + + <details><summary>TODO 4: Click to show/hide answer</summary> .. code-block:: cmake - :caption: CMakeLists.txt - :name: CMakeLists.txt-add_subdirectory + :caption: TODO 4: CMakeLists.txt + :name: CMakeLists.txt-target_include_directories-step2 + + target_include_directories(Tutorial PUBLIC + "${PROJECT_BINARY_DIR}" + "${PROJECT_SOURCE_DIR}/MathFunctions" + ) + +.. raw:: html + + </details> + +Now let's use our library. In ``tutorial.cxx``, include ``MathFunctions.h``: + +.. raw:: html + + <details><summary>TODO 5: Click to show/hide answer</summary> - # add the MathFunctions library - add_subdirectory(MathFunctions) +.. code-block:: c++ + :caption: TODO 5 : tutorial.cxx + :name: tutorial.cxx-include_MathFunctions.h - # add the executable - add_executable(Tutorial tutorial.cxx) + #include "MathFunctions.h" - target_link_libraries(Tutorial PUBLIC MathFunctions) +.. raw:: html - # add the binary tree to the search path for include files - # so that we will find TutorialConfig.h - target_include_directories(Tutorial PUBLIC - "${PROJECT_BINARY_DIR}" - "${PROJECT_SOURCE_DIR}/MathFunctions" - ) + </details> -Now let us make the ``MathFunctions`` library optional. While for the tutorial +Lastly, replace ``sqrt`` with our library function ``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); + +.. raw:: html + + </details> + +Exercise 2 - Making Our Library Optional +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Now let us make the MathFunctions library optional. While for the tutorial there really isn't any need to do so, for larger projects this is a common -occurrence. The first step is to add an option to the top-level -``CMakeLists.txt`` file. +occurrence. + +CMake can do this using the :command:`option` command. This gives users a +variable which they can change when configuring their cmake build. This +setting will be stored in the cache so that the user does not need to set +the value each time they run CMake on a build directory. + +Goal +---- + +Add the option to build without ``MathFunctions``. + + +Helpful Resources +----------------- + +* :command:`if` +* :command:`list` +* :command:`option` +* :command:`cmakedefine <configure_file>` + +Files to Edit +------------- + +* ``CMakeLists.txt`` +* ``tutorial.cxx`` +* ``TutorialConfig.h.in`` + +Getting Started +--------------- + +Start with the resulting files from Exercise 1. Complete ``TODO 7`` through +``TODO 13``. + +First create a variable ``MY_MATH`` 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. + +Then, update ``tutorial.cxx`` and ``TutorialConfig.h.in`` to use ``MY_MATH``. + +Build and Run +------------- + +Since we have our build directory already configured from Exercise 1, we can +rebuild by simply calling the following: + +.. code-block:: console + + cd ../Step2_build + cmake --build . + +Next, run the ``Tutorial`` executable on a few numbers to verify that it's +still correct. + +Now let's update the value of ``USE_MYMATH`` to ``OFF``. The easiest way is to +use the :manual:`cmake-gui <cmake-gui(1)>` or :manual:`ccmake <ccmake(1)>` +if you're in the terminal. Or, alternatively, if you want to change the +option from the command-line, try: + +.. code-block:: console + + cmake ../Step2 -DUSE_MYMATH=OFF + +Now, rebuild the code with the following: + +.. code-block:: console + + cmake --build . + +Then, run the executable again to ensure that it still works with +``USE_MYMATH`` set to ``OFF``. Which function gives better results, ``sqrt`` +or ``mysqrt``? + +Solution +-------- + +The first step is to add an option to the top-level ``CMakeLists.txt`` file. +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. + +.. raw:: html + + <details><summary>TODO 7: Click to show/hide answer</summary> .. literalinclude:: Step3/CMakeLists.txt - :caption: CMakeLists.txt + :caption: TODO 7: CMakeLists.txt :name: CMakeLists.txt-option :language: cmake :start-after: # should we use our own math functions - :end-before: # add the MathFunctions library + :end-before: # configure a header file to pass some of the CMake settings -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. This setting -will be stored in the cache so that the user does not need to set the value -each time they run CMake on a build directory. - -The next change is to make building and linking the ``MathFunctions`` library -conditional. To do this, we will create an ``if`` statement which checks the -value of the option. Inside the ``if`` block, put the -:command:`add_subdirectory` command from above with some additional list -commands to store information needed to link to the library and add the -subdirectory as an include directory in the ``Tutorial`` target. -The end of the top-level ``CMakeLists.txt`` file will now look like the -following: +.. 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``. + +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 +``USE_MYMATH``. Inside the :command:`if` block, put the +:command:`add_subdirectory` command from Exercise 1 with the additional +:command:`list` commands. + +When ``MY_MATH`` is ``ON``, the lists will be generated and will be added to +our project. When ``MY_MATH`` is ``OFF``, the lists stay empty. With this +strategy, we allow users to toggle ``MY_MATH`` to manipulate what library is +used in the build. + +The top-level CMakeLists.txt file will now look like the following: + +.. raw:: html + + <details><summary>TODO 8: Click to show/hide answer</summary> .. literalinclude:: Step3/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-target_link_libraries-EXTRA_LIBS + :caption: TODO 8: CMakeLists.txt + :name: CMakeLists.txt-USE_MYMATH :language: cmake :start-after: # add the MathFunctions library + :end-before: # add the executable + +.. raw:: html + + </details> -Note the use of the variable ``EXTRA_LIBS`` to collect up any optional -libraries to later be linked into the executable. The variable -``EXTRA_INCLUDES`` is used similarly for optional header files. This is a -classic approach when dealing with many optional components, we will cover -the modern approach in the next step. +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: + +.. 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 + +.. raw:: html + + </details> + +Then, we do the same thing with :command:`target_include_directories` and +``EXTRA_INCLUDES``. + +.. 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``, include the ``MathFunctions.h`` header if we -need it: +First, in ``tutorial.cxx``, we include the ``MathFunctions.h`` header if +``MY_MATH`` is defined. + +.. raw:: html + + <details><summary>TODO 11: Click to show/hide answer</summary> .. literalinclude:: Step3/tutorial.cxx - :caption: tutorial.cxx + :caption: TODO 11 : tutorial.cxx :name: tutorial.cxx-ifdef-include :language: c++ :start-after: // should we include the MathFunctions header :end-before: int main -Then, in the same file, make ``USE_MYMATH`` control which square root +.. 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: 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 +.. 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 13: Click to show/hide answer</summary> + .. literalinclude:: Step3/TutorialConfig.h.in - :caption: TutorialConfig.h.in + :caption: TODO 13 : TutorialConfig.h.in :name: TutorialConfig.h.in-cmakedefine :language: c++ :lines: 4 -**Exercise**: Why is it important that we configure ``TutorialConfig.h.in`` +.. 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? -Run the :manual:`cmake <cmake(1)>` executable or the -:manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it -with your chosen build tool. Then run the built Tutorial executable. +Answer +------ -Now let's update the value of ``USE_MYMATH``. The easiest way is to use the -:manual:`cmake-gui <cmake-gui(1)>` or :manual:`ccmake <ccmake(1)>` if you're -in the terminal. Or, alternatively, if you want to change the option from the -command-line, try: +.. raw:: html -.. code-block:: console + <details><summary>Click to show/hide answer</summary> - cmake ../Step2 -DUSE_MYMATH=OFF +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``. -Rebuild and run the tutorial again. +.. raw:: html -Which function gives better results, ``sqrt`` or ``mysqrt``? + </details> diff --git a/Help/guide/tutorial/Complete/CMakeLists.txt b/Help/guide/tutorial/Complete/CMakeLists.txt index 41baf64..3cdaaae 100644 --- a/Help/guide/tutorial/Complete/CMakeLists.txt +++ b/Help/guide/tutorial/Complete/CMakeLists.txt @@ -41,7 +41,7 @@ add_subdirectory(MathFunctions) add_executable(Tutorial tutorial.cxx) set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) -target_link_libraries(Tutorial PUBLIC MathFunctions) +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 @@ -84,6 +84,7 @@ do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") +# setup installer include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") diff --git a/Help/guide/tutorial/Complete/License.txt b/Help/guide/tutorial/Complete/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Complete/License.txt +++ b/Help/guide/tutorial/Complete/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt index 40b9fd2..d256db2 100644 --- a/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Complete/MathFunctions/CMakeLists.txt @@ -56,7 +56,7 @@ target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0") set_property(TARGET MathFunctions PROPERTY SOVERSION "1") -# install rules +# install libs set(installable_libs MathFunctions tutorial_compiler_flags) if(TARGET SqrtLibrary) list(APPEND installable_libs SqrtLibrary) @@ -64,4 +64,5 @@ endif() install(TARGETS ${installable_libs} EXPORT MathFunctionsTargets DESTINATION lib) +# install include headers install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Installing and Testing.rst b/Help/guide/tutorial/Installing and Testing.rst index 394c986..fa13040 100644 --- a/Help/guide/tutorial/Installing and Testing.rst +++ b/Help/guide/tutorial/Installing and Testing.rst @@ -1,95 +1,311 @@ -Step 4: Installing and Testing +Step 5: Installing and Testing ============================== -Now we can start adding install rules and testing support to our project. +.. _`Tutorial Testing Support`: + +Exercise 1 - Install Rules +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Often, it is not enough to only build an executable, it should also be +installable. With CMake, we can specify install rules using the +:command:`install` command. Supporting local installations for your builds in +CMake is often as simple as specifying an install location and the targets and +files to be installed. + +Goal +---- + +Install the ``Tutorial`` executable and the ``MathFunctions`` library. + +Helpful Materials +----------------- + +* :command:`install` -Install Rules +Files to Edit ------------- -The install rules are fairly simple: for ``MathFunctions`` we want to install -the library and header file and for the application we want to install the -executable and configured header. +* ``MathFunctions/CMakeLists.txt`` +* ``CMakeLists.txt`` -So to the end of ``MathFunctions/CMakeLists.txt`` we add: +Getting Started +--------------- -.. literalinclude:: Step5/MathFunctions/CMakeLists.txt - :caption: MathFunctions/CMakeLists.txt - :name: MathFunctions/CMakeLists.txt-install-TARGETS - :language: cmake - :start-after: # install rules +The starting code is provided in the ``Step5`` directory. In this +exercise, complete ``TODO 1`` through ``TODO 4``. -And to the end of the top-level ``CMakeLists.txt`` we add: +First, update ``MathFunctions/CMakeLists.txt`` to install the +``MathFunctions`` and ``tutorial_compiler_flags`` libraries to the ``lib`` +directory. In that same file, specify the install rules needed to install +``MathFunctions.h`` to the ``include`` directory. -.. literalinclude:: Step5/CMakeLists.txt - :caption: CMakeLists.txt - :name: CMakeLists.txt-install-TARGETS - :language: cmake - :start-after: # add the install targets - :end-before: # enable testing +Then, update the top level ``CMakeLists.txt`` to install +the ``Tutorial`` executable to the ``bin`` directory. Lastly, any header files +should be installed to the ``include`` directory. Remember that +``TutorialConfig.h`` is in the :variable:`PROJECT_BINARY_DIR`. -That is all that is needed to create a basic local install of the tutorial. +Build and Run +------------- -Now run the :manual:`cmake <cmake(1)>` executable or the +Make a new directory called ``Step5_build``. Run the +:manual:`cmake <cmake(1)>` executable or the :manual:`cmake-gui <cmake-gui(1)>` to configure the project and then build it with your chosen build tool. -Then run the install step by using the ``install`` option of the -:manual:`cmake <cmake(1)>` command (introduced in 3.15, older versions of -CMake must use ``make install``) from the command line. For -multi-configuration tools, don't forget to use the ``--config`` argument to -specify the configuration. If using an IDE, simply build the ``INSTALL`` -target. This step will install the appropriate header files, libraries, and -executables. For example: +Then, run the install step by using the :option:`--install <cmake --install>` +option of the :manual:`cmake <cmake(1)>` command (introduced in 3.15, older +versions of CMake must use ``make install``) from the command line. This step +will install the appropriate header files, libraries, and executables. +For example: .. code-block:: console cmake --install . +For multi-configuration tools, don't forget to use the +:option:`--config <cmake--build --config>` argument to specify the configuration. + +.. code-block:: console + + cmake --install . --config Release + +If using an IDE, simply build the ``INSTALL`` target. You can build the same +install target from the command line like the following: + +.. code-block:: console + + cmake --build . --target install --config Debug + The CMake variable :variable:`CMAKE_INSTALL_PREFIX` is used to determine the -root of where the files will be installed. If using the ``cmake --install`` -command, the installation prefix can be overridden via the ``--prefix`` -argument. For example: +root of where the files will be installed. If using the :option:`cmake --install` +command, the installation prefix can be overridden via the +:option:`--prefix <cmake--install --prefix>` argument. For example: .. code-block:: console cmake --install . --prefix "/home/myuser/installdir" -Navigate to the install directory and verify that the installed Tutorial runs. +Navigate to the install directory and verify that the installed ``Tutorial`` +runs. -.. _`Tutorial Testing Support`: +Solution +-------- -Testing Support ---------------- +The install rules for our project are fairly simple: -Next let's test our application. At the end of the top-level ``CMakeLists.txt`` -file we can enable testing and then add a number of basic tests to verify that -the application is working correctly. +* For ``MathFunctions``, we want to install the libraries and header file to + the ``lib`` and ``include`` directories respectively. -.. literalinclude:: Step5/CMakeLists.txt +* For the ``Tutorial`` executable, we want to install the executable and + configured header file to the ``bin`` and ``include`` directories + respectively. + +So to the end of ``MathFunctions/CMakeLists.txt`` we add: + +.. raw:: html + + <details><summary>TODO 1: Click to show/hide answer</summary> + +.. literalinclude:: Step6/MathFunctions/CMakeLists.txt + :caption: TODO 1: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-install-TARGETS + :language: cmake + :start-after: # install libs + :end-before: # install include headers + +.. raw:: html + + </details> + +and + +.. raw:: html + + <details><summary>TODO 2: Click to show/hide answer</summary> + +.. literalinclude:: Step6/MathFunctions/CMakeLists.txt + :caption: TODO 2: MathFunctions/CMakeLists.txt + :name: MathFunctions/CMakeLists.txt-install-headers + :language: cmake + :start-after: # install include headers + +.. raw:: html + + </details> + +The install rules for the ``Tutorial`` executable and configured header file +are similar. To the end of the top-level ``CMakeLists.txt`` we add: + +.. raw:: html + + <details><summary>TODO 3,4: Click to show/hide answer</summary> + +.. literalinclude:: Step6/CMakeLists.txt :caption: CMakeLists.txt - :name: CMakeLists.txt-enable_testing + :name: TODO 3,4: CMakeLists.txt-install-TARGETS :language: cmake - :start-after: # enable testing + :start-after: # add the install targets + :end-before: # enable testing + +.. raw:: html + + </details> -The first test simply verifies that the application runs, does not segfault or -otherwise crash, and has a zero return value. This is the basic form of a -CTest test. +That is all that is needed to create a basic local +install of the tutorial. -The next test makes use of the :prop_test:`PASS_REGULAR_EXPRESSION` test -property to verify that the output of the test contains certain strings. In -this case, verifying that the usage message is printed when an incorrect number -of arguments are provided. +Exercise 2 - Testing Support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Lastly, we have a function called ``do_test`` that runs the application and -verifies that the computed square root is correct for given input. For each -invocation of ``do_test``, another test is added to the project with a name, -input, and expected results based on the passed arguments. +CTest offers a way to easily manage tests for your project. Tests can be +added through the :command:`add_test` command. Although it is not +explicitly covered in this tutorial, there is a lot of compatibility +between CTest and other testing frameworks such as :module:`GoogleTest`. -Rebuild the application and then cd to the binary directory and run the -:manual:`ctest <ctest(1)>` executable: ``ctest -N`` and ``ctest -VV``. For +Goal +---- + +Create unit tests for our executable using CTest. + +Helpful Materials +----------------- + +* :command:`enable_testing` +* :command:`add_test` +* :command:`function` +* :command:`set_tests_properties` +* :manual:`ctest <ctest(1)>` + +Files to Edit +------------- + +* ``CMakeLists.txt`` + +Getting Started +--------------- + +The starting source code is provided in the ``Step5`` directory. In this +exercise, complete ``TODO 5`` through ``TODO 9``. + +First, we need to enable testing. Next, begin adding tests to our project +using :command:`add_test`. We will work through adding 3 simple tests and +then you can add additional testing as you see fit. + +Build and Run +------------- + +Navigate to the build directory and rebuild the application. Then, run the +``ctest`` executable: :option:`ctest -N` and :option:`ctest -VV`. For multi-config generators (e.g. Visual Studio), the configuration type must be -specified with the ``-C <mode>`` flag. For example, to run tests in Debug -mode use ``ctest -C Debug -VV`` from the binary directory +specified with the :option:`-C \<mode\> <ctest -C>` flag. For example, to run tests in Debug +mode use ``ctest -C Debug -VV`` from the build directory (not the Debug subdirectory!). Release mode would be executed from the same -location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS`` +location but with a ``-C Release``. Alternatively, build the ``RUN_TESTS`` target from the IDE. + +Solution +-------- + +Let's test our application. At the end of the top-level ``CMakeLists.txt`` +file we first need to enable testing with the +:command:`enable_testing` command. + +.. raw:: html + + <details><summary>TODO 5: Click to show/hide answer</summary> + +.. literalinclude:: Step6/CMakeLists.txt + :caption: TODO 5: CMakeLists.txt + :name: CMakeLists.txt-enable_testing + :language: cmake + :start-after: # enable testing + :end-before: # does the application run + +.. raw:: html + + </details> + +With testing enabled, we will add a number of basic tests to verify +that the application is working correctly. First, we create a test using +:command:`add_test` which runs the ``Tutorial`` executable with the +parameter 25 passed in. For this test, we are not going to check the +executable's computed answer. This test will verify that +application runs, does not segfault or otherwise crash, and has a zero +return value. This is the basic form of a CTest test. + +.. raw:: html + + <details><summary>TODO 6: Click to show/hide answer</summary> + +.. literalinclude:: Step6/CMakeLists.txt + :caption: TODO 6: CMakeLists.txt + :name: CMakeLists.txt-test-runs + :language: cmake + :start-after: # does the application run + :end-before: # does the usage message work + +.. raw:: html + + </details> + +Next, let's use the :prop_test:`PASS_REGULAR_EXPRESSION` test property to +verify that the output of the test contains certain strings. In this case, +verifying that the usage message is printed when an incorrect number of +arguments are provided. + +.. raw:: html + + <details><summary>TODO 7: Click to show/hide answer</summary> + +.. literalinclude:: Step6/CMakeLists.txt + :caption: TODO 7: CMakeLists.txt + :name: CMakeLists.txt-test-usage + :language: cmake + :start-after: # does the usage message work? + :end-before: # define a function to simplify adding tests + +.. raw:: html + + </details> + +The next test we will add verifies the computed value is truly the +square root. + +.. raw:: html + + <details><summary>TODO 8: Click to show/hide answer</summary> + +.. code-block:: cmake + :caption: TODO 8: CMakeLists.txt + :name: CMakeLists.txt-test-standard + + add_test(NAME StandardUse COMMAND Tutorial 4) + set_tests_properties(StandardUse + PROPERTIES PASS_REGULAR_EXPRESSION "4 is 2" + ) + +.. raw:: html + + </details> + +This one test is not enough to give us confidence that it will +work for all values passed in. We should add more tests to verify this. +To easily add more tests, we make a function called ``do_test`` that runs the +application and verifies that the computed square root is correct for +given input. For each invocation of ``do_test``, another test is added to +the project with a name, input, and expected results based on the passed +arguments. + +.. raw:: html + + <details><summary>TODO 9: Click to show/hide answer</summary> + +.. literalinclude:: Step6/CMakeLists.txt + :caption: TODO 9: CMakeLists.txt + :name: CMakeLists.txt-generalized-tests + :language: cmake + :start-after: # define a function to simplify adding tests + +.. raw:: html + + </details> diff --git a/Help/guide/tutorial/Packaging Debug and Release.rst b/Help/guide/tutorial/Packaging Debug and Release.rst index 91b46a7..8c660a3 100644 --- a/Help/guide/tutorial/Packaging Debug and Release.rst +++ b/Help/guide/tutorial/Packaging Debug and Release.rst @@ -10,8 +10,8 @@ possible, however, to setup CPack to bundle multiple build directories and construct a package that contains multiple configurations of the same project. First, we want to ensure that the debug and release builds use different names -for the executables and libraries that will be installed. Let's use `d` as the -postfix for the debug executable and libraries. +for the libraries that will be installed. Let's use `d` as the +postfix for the debug libraries. Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level ``CMakeLists.txt`` file: @@ -41,10 +41,10 @@ Let's also add version numbering to the ``MathFunctions`` library. In :name: MathFunctions/CMakeLists.txt-VERSION-properties :language: cmake :start-after: # setup the version numbering - :end-before: # install rules + :end-before: # install libs From the ``Step12`` directory, create ``debug`` and ``release`` -subbdirectories. The layout will look like: +subdirectories. The layout will look like: .. code-block:: none diff --git a/Help/guide/tutorial/Packaging an Installer.rst b/Help/guide/tutorial/Packaging an Installer.rst index 0ee5db2..11a1952 100644 --- a/Help/guide/tutorial/Packaging an Installer.rst +++ b/Help/guide/tutorial/Packaging an Installer.rst @@ -1,4 +1,4 @@ -Step 7: Packaging an Installer +Step 9: Packaging an Installer ============================== Next suppose that we want to distribute our project to other people so that @@ -11,7 +11,7 @@ installations and package management features. To accomplish this we will use CPack to create platform specific installers. Specifically we need to add a few lines to the bottom of our top-level ``CMakeLists.txt`` file. -.. literalinclude:: Step8/CMakeLists.txt +.. literalinclude:: Step10/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-include-CPack :language: cmake @@ -38,15 +38,15 @@ binary directory run: cpack -To specify the generator, use the ``-G`` option. For multi-config builds, use -``-C`` to specify the configuration. For example: +To specify the generator, use the :option:`-G <cpack -G>` option. For multi-config builds, +use :option:`-C <cpack -C>` to specify the configuration. For example: .. code-block:: console cpack -G ZIP -C Debug For a list of available generators, see :manual:`cpack-generators(7)` or call -``cpack --help``. An :cpack_gen:`archive generator <CPack Archive Generator>` +:option:`cpack --help`. An :cpack_gen:`archive generator <CPack Archive Generator>` like ZIP creates a compressed archive of all *installed* files. To create an archive of the *full* source tree you would type: diff --git a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst index 2d5f70e..1c49c23 100644 --- a/Help/guide/tutorial/Selecting Static or Shared Libraries.rst +++ b/Help/guide/tutorial/Selecting Static or Shared Libraries.rst @@ -1,5 +1,5 @@ -Step 9: Selecting Static or Shared Libraries -============================================ +Step 10: Selecting Static or Shared Libraries +============================================= In this section we will show how the :variable:`BUILD_SHARED_LIBS` variable can be used to control the default behavior of :command:`add_library`, @@ -19,7 +19,7 @@ library. The first step is to update the starting section of the top-level ``CMakeLists.txt`` to look like: -.. literalinclude:: Step10/CMakeLists.txt +.. literalinclude:: Step11/CMakeLists.txt :caption: CMakeLists.txt :name: CMakeLists.txt-option-BUILD_SHARED_LIBS :language: cmake @@ -33,7 +33,7 @@ explicitly require that SqrtLibrary is built statically. The end result is that ``MathFunctions/CMakeLists.txt`` should look like: -.. literalinclude:: Step10/MathFunctions/CMakeLists.txt +.. literalinclude:: Step11/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-add_library-STATIC :language: cmake @@ -42,7 +42,7 @@ The end result is that ``MathFunctions/CMakeLists.txt`` should look like: Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and ``detail`` namespaces: -.. literalinclude:: Step10/MathFunctions/mysqrt.cxx +.. literalinclude:: Step11/MathFunctions/mysqrt.cxx :caption: MathFunctions/mysqrt.cxx :name: MathFunctions/mysqrt.cxx-namespace :language: c++ @@ -56,7 +56,7 @@ uses ``USE_MYMATH``: Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines: -.. literalinclude:: Step10/MathFunctions/MathFunctions.h +.. literalinclude:: Step11/MathFunctions/MathFunctions.h :caption: MathFunctions/MathFunctions.h :name: MathFunctions/MathFunctions.h :language: c++ @@ -67,7 +67,7 @@ library that has position independent code. The solution to this is to explicitly set the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property of SqrtLibrary to be ``True`` no matter the build type. -.. literalinclude:: Step10/MathFunctions/CMakeLists.txt +.. literalinclude:: Step11/MathFunctions/CMakeLists.txt :caption: MathFunctions/CMakeLists.txt :name: MathFunctions/CMakeLists.txt-POSITION_INDEPENDENT_CODE :language: cmake diff --git a/Help/guide/tutorial/Step1/CMakeLists.txt b/Help/guide/tutorial/Step1/CMakeLists.txt new file mode 100644 index 0000000..6fcce90 --- /dev/null +++ b/Help/guide/tutorial/Step1/CMakeLists.txt @@ -0,0 +1,16 @@ +# TODO 1: Set the minimum required version of CMake to be 3.10 + +# TODO 2: Create a project named Tutorial + +# TODO 7: Set the project version number as 1.0 in the above project command + +# TODO 6: Set the variable CMAKE_CXX_STANDARD to 11 +# and the variable CMAKE_CXX_STANDARD_REQUIRED to True + +# TODO 8: Use configure_file to configure and copy TutorialConfig.h.in to +# TutorialConfig.h + +# TODO 3: Add an executable called Tutorial to the project +# Hint: Be sure to specify the source file as tutorial.cxx + +# TODO 9: Use target_include_directories to include ${PROJECT_BINARY_DIR} diff --git a/Help/guide/tutorial/Step1/TutorialConfig.h.in b/Help/guide/tutorial/Step1/TutorialConfig.h.in new file mode 100644 index 0000000..990bfbd --- /dev/null +++ b/Help/guide/tutorial/Step1/TutorialConfig.h.in @@ -0,0 +1,2 @@ +// the configured options and settings for Tutorial +// TODO 10: Define Tutorial_VERSION_MAJOR and Tutorial_VERSION_MINOR diff --git a/Help/guide/tutorial/Step1/tutorial.cxx b/Help/guide/tutorial/Step1/tutorial.cxx index 08323bf..64d0916 100644 --- a/Help/guide/tutorial/Step1/tutorial.cxx +++ b/Help/guide/tutorial/Step1/tutorial.cxx @@ -1,17 +1,22 @@ // A simple program that computes the square root of a number #include <cmath> -#include <cstdlib> +#include <cstdlib> // TODO 5: Remove this line #include <iostream> #include <string> +// TODO 11: Include TutorialConfig.h + int main(int argc, char* argv[]) { if (argc < 2) { + // TODO 12: Create a print statement using Tutorial_VERSION_MAJOR + // and Tutorial_VERSION_MINOR std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; } // convert input to double + // TODO 4: Replace atof(argv[1]) with std::stod(argv[1]) const double inputValue = atof(argv[1]); // calculate square root diff --git a/Help/guide/tutorial/Step10/CMakeLists.txt b/Help/guide/tutorial/Step10/CMakeLists.txt index 55dc409..5c661aa 100644 --- a/Help/guide/tutorial/Step10/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/CMakeLists.txt @@ -1,29 +1,37 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) -# control where the static and shared libraries are built so that on windows -# we don't need to tinker with the path to run the executable -set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) -option(BUILD_SHARED_LIBS "Build using shared libraries" ON) +# should we use our own math functions +option(USE_MYMATH "Use tutorial provided math implementation" ON) -# configure a header file to pass the version number only +# 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 -add_subdirectory(MathFunctions) +if(USE_MYMATH) + add_subdirectory(MathFunctions) + list(APPEND EXTRA_LIBS MathFunctions) +endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC MathFunctions) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -66,6 +74,7 @@ do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") +# setup installer include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") diff --git a/Help/guide/tutorial/Step10/License.txt b/Help/guide/tutorial/Step10/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Step10/License.txt +++ b/Help/guide/tutorial/Step10/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt index 0bfe20c..fa73321 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step10/MathFunctions/CMakeLists.txt @@ -1,55 +1,32 @@ -# add the library that runs -add_library(MathFunctions MathFunctions.cxx) +# 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 + ) # 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} - ) + INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR} + ) -# should we use our own math functions -option(USE_MYMATH "Use tutorial provided math implementation" ON) -if(USE_MYMATH) +# link our compiler flags interface library +target_link_libraries(MathFunctions tutorial_compiler_flags) - target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") - - # 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 - ) - - # 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} - ) - - # state that SqrtLibrary need PIC when the default is shared libraries - set_target_properties(SqrtLibrary PROPERTIES - POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} - ) - - target_link_libraries(MathFunctions PRIVATE SqrtLibrary) -endif() - -# define the symbol stating we are using the declspec(dllexport) when -# building on windows -target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") - -# install rules -set(installable_libs MathFunctions) -if(TARGET SqrtLibrary) - list(APPEND installable_libs SqrtLibrary) -endif() +# install libs +set(installable_libs MathFunctions tutorial_compiler_flags) install(TARGETS ${installable_libs} DESTINATION lib) +# install include headers install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h index 3fb547b..cd36bcc 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h +++ b/Help/guide/tutorial/Step10/MathFunctions/MathFunctions.h @@ -1,14 +1 @@ - -#if defined(_WIN32) -# if defined(EXPORTING_MYMATH) -# define DECLSPEC __declspec(dllexport) -# else -# define DECLSPEC __declspec(dllimport) -# endif -#else // non windows -# define DECLSPEC -#endif - -namespace mathfunctions { -double DECLSPEC sqrt(double x); -} +double mysqrt(double x); diff --git a/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx index 8153f18..7d80ee9 100644 --- a/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step10/MathFunctions/mysqrt.cxx @@ -5,8 +5,6 @@ // include the generated table #include "Table.h" -namespace mathfunctions { -namespace detail { // a hack square root calculation using simple operations double mysqrt(double x) { @@ -33,5 +31,3 @@ 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 7e4d7fa..e23f521 100644 --- a/Help/guide/tutorial/Step10/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step10/TutorialConfig.h.in @@ -1,3 +1,4 @@ // 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 37a0333..b3c6a4f 100644 --- a/Help/guide/tutorial/Step10/tutorial.cxx +++ b/Help/guide/tutorial/Step10/tutorial.cxx @@ -1,11 +1,15 @@ // 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) { @@ -19,7 +23,12 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); - const double outputValue = mathfunctions::sqrt(inputValue); + // which square root function should we use? +#ifdef USE_MYMATH + const double outputValue = mysqrt(inputValue); +#else + const double outputValue = sqrt(inputValue); +#endif std::cout << "The square root of " << inputValue << " is " << outputValue << std::endl; diff --git a/Help/guide/tutorial/Step11/CMakeLists.txt b/Help/guide/tutorial/Step11/CMakeLists.txt index 1044748..046bfc9 100644 --- a/Help/guide/tutorial/Step11/CMakeLists.txt +++ b/Help/guide/tutorial/Step11/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) +# specify the C++ standard add_library(tutorial_compiler_flags INTERFACE) target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) @@ -31,7 +32,7 @@ add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC MathFunctions) +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 @@ -46,7 +47,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" ) # enable testing -enable_testing() +include(CTest) # does the application run add_test(NAME Runs COMMAND Tutorial 25) @@ -74,6 +75,7 @@ do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") +# setup installer include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") diff --git a/Help/guide/tutorial/Step11/License.txt b/Help/guide/tutorial/Step11/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Step11/License.txt +++ b/Help/guide/tutorial/Step11/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt index 0d287ca..a60fb63 100644 --- a/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step11/MathFunctions/CMakeLists.txt @@ -47,13 +47,14 @@ endif() target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # define the symbol stating we are using the declspec(dllexport) when -#building on windows +# building on windows target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") -# install rules +# 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/Step11/tutorial.cxx b/Help/guide/tutorial/Step11/tutorial.cxx index a4f44d5..37a0333 100644 --- a/Help/guide/tutorial/Step11/tutorial.cxx +++ b/Help/guide/tutorial/Step11/tutorial.cxx @@ -1,5 +1,6 @@ // A simple program that computes the square root of a number #include <iostream> +#include <sstream> #include <string> #include "MathFunctions.h" diff --git a/Help/guide/tutorial/Step12/CMakeLists.txt b/Help/guide/tutorial/Step12/CMakeLists.txt index 63f9643..220ed4b 100644 --- a/Help/guide/tutorial/Step12/CMakeLists.txt +++ b/Help/guide/tutorial/Step12/CMakeLists.txt @@ -37,7 +37,7 @@ add_subdirectory(MathFunctions) # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC MathFunctions) +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 @@ -80,6 +80,7 @@ do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") +# setup installer include(InstallRequiredSystemLibraries) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") diff --git a/Help/guide/tutorial/Step12/License.txt b/Help/guide/tutorial/Step12/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Step12/License.txt +++ b/Help/guide/tutorial/Step12/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt index d5961da..a85f3cb 100644 --- a/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step12/MathFunctions/CMakeLists.txt @@ -52,7 +52,7 @@ target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags) # building on windows target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH") -# install rules +# install libs set(installable_libs MathFunctions tutorial_compiler_flags) if(TARGET SqrtLibrary) list(APPEND installable_libs SqrtLibrary) @@ -60,4 +60,5 @@ endif() install(TARGETS ${installable_libs} EXPORT MathFunctionsTargets DESTINATION lib) +# install include headers install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step2/CMakeLists.txt b/Help/guide/tutorial/Step2/CMakeLists.txt index 7aa59e9..2f7d56e 100644 --- a/Help/guide/tutorial/Step2/CMakeLists.txt +++ b/Help/guide/tutorial/Step2/CMakeLists.txt @@ -7,13 +7,36 @@ project(Tutorial VERSION 1.0) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) +# TODO 7: Create a variable MY_MATH 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 new file mode 100644 index 0000000..b7779b7 --- /dev/null +++ b/Help/guide/tutorial/Step2/MathFunctions/CMakeLists.txt @@ -0,0 +1,2 @@ +# TODO 1: Add a library called MathFunctions +# Hint: You will need the add_library command diff --git a/Help/guide/tutorial/Step2/TutorialConfig.h.in b/Help/guide/tutorial/Step2/TutorialConfig.h.in index 7e4d7fa..adb4c55 100644 --- a/Help/guide/tutorial/Step2/TutorialConfig.h.in +++ b/Help/guide/tutorial/Step2/TutorialConfig.h.in @@ -1,3 +1,5 @@ // 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 MY_MATH diff --git a/Help/guide/tutorial/Step2/tutorial.cxx b/Help/guide/tutorial/Step2/tutorial.cxx index 53b0810..f83aa7e 100644 --- a/Help/guide/tutorial/Step2/tutorial.cxx +++ b/Help/guide/tutorial/Step2/tutorial.cxx @@ -5,6 +5,10 @@ #include "TutorialConfig.h" +// TODO 11: Only include MathFunctions if MY_MATH is defined + +// TODO 5: Include MathFunctions.h + int main(int argc, char* argv[]) { if (argc < 2) { @@ -18,6 +22,10 @@ int main(int argc, char* argv[]) // convert input to double const double inputValue = std::stod(argv[1]); + // TODO 12: Use mysqrt if MY_MATH is defined and sqrt otherwise + + // TODO 6: Replace sqrt with mysqrt + // calculate square root const double outputValue = sqrt(inputValue); std::cout << "The square root of " << inputValue << " is " << outputValue diff --git a/Help/guide/tutorial/Step3/CMakeLists.txt b/Help/guide/tutorial/Step3/CMakeLists.txt index 1c12816..007770a 100644 --- a/Help/guide/tutorial/Step3/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/CMakeLists.txt @@ -14,6 +14,8 @@ option(USE_MYMATH "Use tutorial provided math implementation" ON) # to the source code configure_file(TutorialConfig.h.in TutorialConfig.h) +# TODO 2: Remove EXTRA_INCLUDES list + # add the MathFunctions library if(USE_MYMATH) add_subdirectory(MathFunctions) @@ -26,6 +28,8 @@ add_executable(Tutorial tutorial.cxx) target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +# TODO 3: Remove use of EXTRA_INCLUDES + # 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/Step3/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt index 8b443a6..7bf05e0 100644 --- a/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step3/MathFunctions/CMakeLists.txt @@ -1 +1,5 @@ add_library(MathFunctions 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 diff --git a/Help/guide/tutorial/Step4/CMakeLists.txt b/Help/guide/tutorial/Step4/CMakeLists.txt index 38e9b1f..fa4aab2 100644 --- a/Help/guide/tutorial/Step4/CMakeLists.txt +++ b/Help/guide/tutorial/Step4/CMakeLists.txt @@ -1,12 +1,36 @@ +# TODO 4: Update the minimum required version to 3.15 + cmake_minimum_required(VERSION 3.10) # set the project name and version project(Tutorial VERSION 1.0) +# TODO 1: Replace the following code by: +# * Creating an interface library called tutorial_compiler_flags +# Hint: use add_library() with the INTERFACE signature +# * Add compiler feature cxx_std_11 to tutorial_compiler_flags +# Hint: Use target_compile_features() + # specify the C++ standard set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True) +# TODO 5: Create helper variables to determine which compiler we are using: +# * Create a new variable gcc_like_cxx that is true if we are using CXX and +# any of the following compilers: ARMClang, AppleClang, Clang, GNU, LCC +# * Create a new variable msvc_cxx that is true if we are using CXX and MSVC +# Hint: Use set() and COMPILE_LANG_AND_ID + +# TODO 6: Add warning flag compile options to the interface library +# tutorial_compiler_flags. +# * For gcc_like_cxx, add flags -Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused +# * For msvc_cxx, add flags -W3 +# Hint: Use target_compile_options() + +# TODO 7: With nested generator expressions, only use the flags for the +# build-tree +# Hint: Use BUILD_INTERFACE + # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -23,6 +47,8 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) +# TODO 2: Link to tutorial_compiler_flags + target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) # add the binary tree to the search path for include files diff --git a/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt index 0515852..5f7369c 100644 --- a/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step4/MathFunctions/CMakeLists.txt @@ -5,3 +5,5 @@ add_library(MathFunctions mysqrt.cxx) target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) + +# TODO 3: Link to tutorial_compiler_flags diff --git a/Help/guide/tutorial/Step5/CMakeLists.txt b/Help/guide/tutorial/Step5/CMakeLists.txt index 82d00c8..a8f241a 100644 --- a/Help/guide/tutorial/Step5/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,7 +31,7 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -30,37 +39,26 @@ target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" ) -# add the install targets -install(TARGETS Tutorial DESTINATION bin) -install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" - DESTINATION include - ) +# TODO 3: Install Tutorial in the bin directory +# Hint: Use the TARGETS and DESTINATION parameters + +# TODO 4: Install Tutorial.h to the include directory +# Hint: Use the FILES and DESTINATION parameters -# enable testing -enable_testing() +# TODO 5: Enable testing -# does the application run -add_test(NAME Runs COMMAND Tutorial 25) +# TODO 6: Add a test called Runs which runs the following command: +# $ Tutorial 25 -# does the usage message work? -add_test(NAME Usage COMMAND Tutorial) -set_tests_properties(Usage - PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number" - ) +# TODO 7: Add a test called Usage which runs the following command: +# $ Tutorial +# Make sure the expected output is displayed. +# Hint: Use the PASS_REGULAR_EXPRESSION property with "Usage.*number" -# define a function to simplify adding tests -function(do_test target arg result) - add_test(NAME Comp${arg} COMMAND ${target} ${arg}) - set_tests_properties(Comp${arg} - PROPERTIES PASS_REGULAR_EXPRESSION ${result} - ) -endfunction() +# TODO 8: Add a test which runs the following command: +# $ Tutorial 4 +# Make sure the result is correct. +# Hint: Use the PASS_REGULAR_EXPRESSION property with "4 is 2" -# do a bunch of result based tests -do_test(Tutorial 4 "4 is 2") -do_test(Tutorial 9 "9 is 3") -do_test(Tutorial 5 "5 is 2.236") -do_test(Tutorial 7 "7 is 2.645") -do_test(Tutorial 25 "25 is 5") -do_test(Tutorial -25 "-25 is (-nan|nan|0)") -do_test(Tutorial 0.0001 "0.0001 is 0.01") +# TODO 9: Add more tests. Create a function called do_test to avoid copy + +# paste. Test the following values: 4, 9, 5, 7, 25, -25 and 0.00001. diff --git a/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt index b12f27d..6cd88d7 100644 --- a/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step5/MathFunctions/CMakeLists.txt @@ -6,6 +6,13 @@ target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) -# install rules -install(TARGETS MathFunctions DESTINATION lib) -install(FILES MathFunctions.h DESTINATION include) +# link our compiler flags interface library +target_link_libraries(MathFunctions 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) +# Then install the installable libraries to the lib folder. +# Hint: Use the TARGETS and DESTINATION parameters + +# TODO 2: Install the library headers to the include folder. +# Hint: Use the FILES and DESTINATION parameters diff --git a/Help/guide/tutorial/Step6/CMakeLists.txt b/Help/guide/tutorial/Step6/CMakeLists.txt index 82d00c8..da9e852 100644 --- a/Help/guide/tutorial/Step6/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,7 +31,7 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} 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/CTestConfig.cmake b/Help/guide/tutorial/Step6/CTestConfig.cmake new file mode 100644 index 0000000..73efdb1 --- /dev/null +++ b/Help/guide/tutorial/Step6/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt index 42e098a..b4724c4 100644 --- a/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step6/MathFunctions/CMakeLists.txt @@ -6,29 +6,11 @@ target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ) -# 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) +# link our compiler flags interface library +target_link_libraries(MathFunctions tutorial_compiler_flags) -# add compile definitions -if(HAVE_LOG AND HAVE_EXP) - target_compile_definitions(MathFunctions - PRIVATE "HAVE_LOG" "HAVE_EXP") -endif() - -# install rules -install(TARGETS MathFunctions DESTINATION lib) +# install libs +set(installable_libs MathFunctions tutorial_compiler_flags) +install(TARGETS ${installable_libs} DESTINATION lib) +# install include headers install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx deleted file mode 100644 index ee58556..0000000 --- a/Help/guide/tutorial/Step6/MathFunctions/MakeTable.cxx +++ /dev/null @@ -1,25 +0,0 @@ -// A simple program that builds a sqrt table -#include <cmath> -#include <fstream> -#include <iostream> - -int main(int argc, char* argv[]) -{ - // make sure we have enough arguments - if (argc < 2) { - return 1; - } - - std::ofstream fout(argv[1], std::ios_base::out); - const bool fileOpen = fout.is_open(); - if (fileOpen) { - fout << "double sqrtTable[] = {" << std::endl; - for (int i = 0; i < 10; ++i) { - fout << sqrt(static_cast<double>(i)) << "," << std::endl; - } - // close the table with a zero - fout << "0};" << std::endl; - fout.close(); - } - return fileOpen ? 0 : 1; // return 0 if wrote the file -} diff --git a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx index 7eecd26..abe767d 100644 --- a/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step6/MathFunctions/mysqrt.cxx @@ -1,4 +1,3 @@ -#include <cmath> #include <iostream> #include "MathFunctions.h" @@ -10,12 +9,6 @@ double mysqrt(double x) return 0; } - // if we have both log and exp then use them -#if defined(HAVE_LOG) && defined(HAVE_EXP) - double result = std::exp(std::log(x) * 0.5); - std::cout << "Computing sqrt of " << x << " to be " << result - << " using log and exp" << std::endl; -#else double result = x; // do ten iterations @@ -27,6 +20,5 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } -#endif return result; } diff --git a/Help/guide/tutorial/Step7/CMakeLists.txt b/Help/guide/tutorial/Step7/CMakeLists.txt index 82d00c8..d26a90c 100644 --- a/Help/guide/tutorial/Step7/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,7 +31,7 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -37,7 +46,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" ) # enable testing -enable_testing() +include(CTest) # does the application run add_test(NAME Runs COMMAND Tutorial 25) diff --git a/Help/guide/tutorial/Step7/CTestConfig.cmake b/Help/guide/tutorial/Step7/CTestConfig.cmake new file mode 100644 index 0000000..73efdb1 --- /dev/null +++ b/Help/guide/tutorial/Step7/CTestConfig.cmake @@ -0,0 +1,7 @@ +set(CTEST_PROJECT_NAME "CMakeTutorial") +set(CTEST_NIGHTLY_START_TIME "00:00:00 EST") + +set(CTEST_DROP_METHOD "http") +set(CTEST_DROP_SITE "my.cdash.org") +set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial") +set(CTEST_DROP_SITE_CDASH TRUE) diff --git a/Help/guide/tutorial/Step7/License.txt b/Help/guide/tutorial/Step7/License.txt deleted file mode 100644 index c62d00b..0000000 --- a/Help/guide/tutorial/Step7/License.txt +++ /dev/null @@ -1,2 +0,0 @@ -This is the open source License.txt file introduced in -CMake/Tutorial/Step7... diff --git a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt index 9ede4b3..b4724c4 100644 --- a/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step7/MathFunctions/CMakeLists.txt @@ -1,29 +1,16 @@ -# 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 mysqrt.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} ) -# install rules -install(TARGETS MathFunctions DESTINATION lib) +# link our compiler flags interface library +target_link_libraries(MathFunctions tutorial_compiler_flags) + +# install libs +set(installable_libs MathFunctions tutorial_compiler_flags) +install(TARGETS ${installable_libs} DESTINATION lib) +# install include headers install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx b/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx deleted file mode 100644 index ee58556..0000000 --- a/Help/guide/tutorial/Step7/MathFunctions/MakeTable.cxx +++ /dev/null @@ -1,25 +0,0 @@ -// A simple program that builds a sqrt table -#include <cmath> -#include <fstream> -#include <iostream> - -int main(int argc, char* argv[]) -{ - // make sure we have enough arguments - if (argc < 2) { - return 1; - } - - std::ofstream fout(argv[1], std::ios_base::out); - const bool fileOpen = fout.is_open(); - if (fileOpen) { - fout << "double sqrtTable[] = {" << std::endl; - for (int i = 0; i < 10; ++i) { - fout << sqrt(static_cast<double>(i)) << "," << std::endl; - } - // close the table with a zero - fout << "0};" << std::endl; - fout.close(); - } - return fileOpen ? 0 : 1; // return 0 if wrote the file -} diff --git a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx index 7d80ee9..abe767d 100644 --- a/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step7/MathFunctions/mysqrt.cxx @@ -2,9 +2,6 @@ #include "MathFunctions.h" -// include the generated table -#include "Table.h" - // a hack square root calculation using simple operations double mysqrt(double x) { @@ -12,12 +9,7 @@ double mysqrt(double x) return 0; } - // use the table to help find an initial value double result = x; - if (x >= 1 && x < 10) { - std::cout << "Use the table to help find an initial value " << std::endl; - result = sqrtTable[static_cast<int>(x)]; - } // do ten iterations for (int i = 0; i < 10; ++i) { @@ -28,6 +20,5 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } - return result; } diff --git a/Help/guide/tutorial/Step8/CMakeLists.txt b/Help/guide/tutorial/Step8/CMakeLists.txt index 4c78b94..cb87281 100644 --- a/Help/guide/tutorial/Step8/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/CMakeLists.txt @@ -1,11 +1,21 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) + # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,7 +32,7 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -37,7 +47,7 @@ install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h" ) # enable testing -enable_testing() +include(CTest) # does the application run add_test(NAME Runs COMMAND Tutorial 25) @@ -64,11 +74,3 @@ do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") - -# setup installer -include(InstallRequiredSystemLibraries) -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") -set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") -set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}") -set(CPACK_SOURCE_GENERATOR "TGZ") -include(CPack) diff --git a/Help/guide/tutorial/Step8/License.txt b/Help/guide/tutorial/Step8/License.txt deleted file mode 100644 index c62d00b..0000000 --- a/Help/guide/tutorial/Step8/License.txt +++ /dev/null @@ -1,2 +0,0 @@ -This is the open source License.txt file introduced in -CMake/Tutorial/Step7... diff --git a/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt index 9ede4b3..f81b563 100644 --- a/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step8/MathFunctions/CMakeLists.txt @@ -1,29 +1,39 @@ -# 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 mysqrt.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} ) -# install rules -install(TARGETS MathFunctions DESTINATION lib) +# 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() + +# install libs +set(installable_libs MathFunctions tutorial_compiler_flags) +install(TARGETS ${installable_libs} DESTINATION lib) +# install include headers install(FILES MathFunctions.h DESTINATION include) diff --git a/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx index 7d80ee9..7eecd26 100644 --- a/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx +++ b/Help/guide/tutorial/Step8/MathFunctions/mysqrt.cxx @@ -1,10 +1,8 @@ +#include <cmath> #include <iostream> #include "MathFunctions.h" -// include the generated table -#include "Table.h" - // a hack square root calculation using simple operations double mysqrt(double x) { @@ -12,12 +10,13 @@ double mysqrt(double x) return 0; } - // use the table to help find an initial value + // if we have both log and exp then use them +#if defined(HAVE_LOG) && defined(HAVE_EXP) + double result = std::exp(std::log(x) * 0.5); + std::cout << "Computing sqrt of " << x << " to be " << result + << " using log and exp" << std::endl; +#else double result = x; - if (x >= 1 && x < 10) { - std::cout << "Use the table to help find an initial value " << std::endl; - result = sqrtTable[static_cast<int>(x)]; - } // do ten iterations for (int i = 0; i < 10; ++i) { @@ -28,6 +27,6 @@ double mysqrt(double x) result = result + 0.5 * delta / result; std::cout << "Computing sqrt of " << x << " to be " << result << std::endl; } - +#endif return result; } diff --git a/Help/guide/tutorial/Step9/CMakeLists.txt b/Help/guide/tutorial/Step9/CMakeLists.txt index 6bae26e..d26a90c 100644 --- a/Help/guide/tutorial/Step9/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/CMakeLists.txt @@ -1,11 +1,20 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.15) # set the project name and version project(Tutorial VERSION 1.0) # specify the C++ standard -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED True) +add_library(tutorial_compiler_flags INTERFACE) +target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11) + +# add compiler warning flags just when building this project via +# the BUILD_INTERFACE genex +set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU,LCC>") +set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>") +target_compile_options(tutorial_compiler_flags INTERFACE + "$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>" + "$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>" +) # should we use our own math functions option(USE_MYMATH "Use tutorial provided math implementation" ON) @@ -22,7 +31,7 @@ endif() # add the executable add_executable(Tutorial tutorial.cxx) -target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS}) +target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS} tutorial_compiler_flags) # add the binary tree to the search path for include files # so that we will find TutorialConfig.h @@ -64,10 +73,3 @@ do_test(Tutorial 7 "7 is 2.645") do_test(Tutorial 25 "25 is 5") do_test(Tutorial -25 "-25 is (-nan|nan|0)") do_test(Tutorial 0.0001 "0.0001 is 0.01") - -include(InstallRequiredSystemLibraries) -set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") -set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}") -set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}") -set(CPACK_SOURCE_GENERATOR "TGZ") -include(CPack) diff --git a/Help/guide/tutorial/Step9/License.txt b/Help/guide/tutorial/Step9/License.txt index c62d00b..85760e5 100644 --- a/Help/guide/tutorial/Step9/License.txt +++ b/Help/guide/tutorial/Step9/License.txt @@ -1,2 +1,2 @@ This is the open source License.txt file introduced in -CMake/Tutorial/Step7... +CMake/Tutorial/Step9... diff --git a/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt index 50f0701..8e04f97 100644 --- a/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt +++ b/Help/guide/tutorial/Step9/MathFunctions/CMakeLists.txt @@ -16,12 +16,19 @@ add_library(MathFunctions # 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} ) -# install rules -install(TARGETS MathFunctions DESTINATION lib) +# link our compiler flags interface library +target_link_libraries(MathFunctions tutorial_compiler_flags) + +# install libs +set(installable_libs MathFunctions tutorial_compiler_flags) +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 deleted file mode 100644 index 0145300..0000000 --- a/Help/guide/tutorial/Step9/MathFunctions/MathFunctions.cxx +++ /dev/null @@ -1,19 +0,0 @@ - -#include "MathFunctions.h" - -#include <cmath> - -#ifdef USE_MYMATH -# include "mysqrt.h" -#endif - -namespace mathfunctions { -double sqrt(double x) -{ -#ifdef USE_MYMATH - return detail::mysqrt(x); -#else - return std::sqrt(x); -#endif -} -} diff --git a/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h b/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h deleted file mode 100644 index e1c42ef..0000000 --- a/Help/guide/tutorial/Step9/MathFunctions/mysqrt.h +++ /dev/null @@ -1,6 +0,0 @@ - -namespace mathfunctions { -namespace detail { -double mysqrt(double x); -} -} diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst index 09553cb..1ab0009 100644 --- a/Help/guide/tutorial/index.rst +++ b/Help/guide/tutorial/index.rst @@ -24,13 +24,13 @@ provides the complete solution for the previous step. A Basic Starting Point Adding a Library Adding Usage Requirements for a Library + Adding Generator Expressions Installing and Testing + Adding Support for a Testing Dashboard Adding System Introspection Adding a Custom Command and Generated File Packaging an Installer - Adding Support for a Testing Dashboard Selecting Static or Shared Libraries - Adding Generator Expressions Adding Export Configuration Packaging Debug and Release diff --git a/Help/guide/user-interaction/index.rst b/Help/guide/user-interaction/index.rst index ba8196b..3355992 100644 --- a/Help/guide/user-interaction/index.rst +++ b/Help/guide/user-interaction/index.rst @@ -71,8 +71,8 @@ The CMake tooling may report warnings which are intended for the provider of the software, not intended for the consumer of the software. Such warnings end with "This warning is for project developers". Users may disable -such warnings by passing the ``-Wno-dev`` flag to -:manual:`cmake(1)`. +such warnings by passing the :option:`-Wno-dev <cmake -Wno-dev>` +flag to :manual:`cmake(1)`. cmake-gui tool -------------- @@ -153,13 +153,13 @@ platform. Usually, the default generator is sufficient to allow the user to proceed to build the software. The user may override the default generator with -the ``-G`` option: +the :option:`-G <cmake -G>` option: .. code-block:: console $ cmake .. -G Ninja -The output of ``cmake --help`` includes a list of +The output of :option:`cmake --help` includes a list of :manual:`generators <cmake-generators(7)>` available for the user to choose from. Note that generator names are case sensitive. @@ -196,7 +196,8 @@ VisualC++ compiler, or a combination of the two: $ cmake .. -G "Visual Studio 16 2019" Visual Studio generators can target different architectures. -One can specify the target architecture using the `-A` option: +One can specify the target architecture using the +:option:`-A <cmake -A>` option: .. code-block:: console @@ -214,8 +215,8 @@ generator to use, typically a choice between a ``Makefile`` or a ``Ninja`` based generator. Note that it is not possible to change the generator -with ``-G`` after the first invocation of CMake. To -change the generator, the build directory must be +with :option:`-G <cmake -G>` after the first invocation of CMake. +To change the generator, the build directory must be deleted and the build must be started from scratch. When generating Visual Studio project and solutions @@ -223,7 +224,7 @@ files several other options are available to use when initially running :manual:`cmake(1)`. The Visual Studio toolset can be specified with the -``-T`` option: +:option:`cmake -T` option: .. code-block:: console @@ -232,9 +233,9 @@ The Visual Studio toolset can be specified with the $ # Build targeting Windows XP $ cmake.exe .. -G "Visual Studio 16 2019" -A x64 -T v120_xp -Whereas the ``-A`` option specifies the _target_ -architecture, the ``-T`` option can be used to specify -details of the toolchain used. For example, `-Thost=x64` +Whereas the :option:`-A <cmake -A>` option specifies the _target_ +architecture, the :option:`-T <cmake -T>` option can be used to specify +details of the toolchain used. For example, ``-Thost=x64`` can be given to select the 64-bit version of the host tools. The following demonstrates how to use 64-bit tools and also build for a 64-bit target architecture: @@ -337,7 +338,7 @@ or later on a subsequent invocation of $ cd build $ cmake . -DCMAKE_BUILD_TYPE=Debug -The ``-U`` flag may be used to unset variables +The :option:`-U <cmake -U>` flag may be used to unset variables on the :manual:`cmake(1)` command line: .. code-block:: console @@ -351,7 +352,7 @@ on the command line can be modified using the The :manual:`cmake(1)` tool allows specifying a file to use to populate the initial cache using -the ``-C`` option. This can be useful to simplify +the :option:`-C <cmake -C>` option. This can be useful to simplify commands and scripts which repeatedly require the same cache entries. @@ -427,10 +428,10 @@ Using presets on the command-line --------------------------------- When using the :manual:`cmake(1)` command line tool, a -preset can be invoked by using the ``--preset`` option. If -``--preset`` is specified, the generator and build -directory are not required, but can be specified to -override them. For example, if you have the following +preset can be invoked by using the :option:`--preset <cmake --preset>` +option. If :option:`--preset <cmake --preset>` is specified, +the generator and build directory are not required, but can be +specified to override them. For example, if you have the following ``CMakePresets.json`` file: .. code-block:: json @@ -502,23 +503,25 @@ command may be invoked in the build directory: $ cmake --build . -The ``--build`` flag enables a particular mode of -operation for the :manual:`cmake(1)` tool. It invokes -the :variable:`CMAKE_MAKE_PROGRAM` command associated -with the :manual:`generator <cmake-generators(7)>`, or +The :option:`--build <cmake --build>` flag enables a +particular mode of operation for the :manual:`cmake(1)` +tool. It invokes the :variable:`CMAKE_MAKE_PROGRAM` +command associated with the +:manual:`generator <cmake-generators(7)>`, or the build tool configured by the user. -The ``--build`` mode also accepts the parameter -``--target`` to specify a particular target to build, -for example a particular library, executable or -custom target, or a particular special target like -``install``: +The :option:`--build <cmake --build>` mode also accepts +the parameter :option:`--target <cmake--build --target>` to +specify a particular target to build, for example a +particular library, executable or custom target, or a +particular special target like ``install``: .. code-block:: console $ cmake --build . --target myexe -The ``--build`` mode also accepts a ``--config`` parameter +The :option:`--build <cmake --build>` mode also accepts a +:option:`--config <cmake--build --config>` parameter in the case of multi-config generators to specify which particular configuration to build: @@ -526,23 +529,23 @@ particular configuration to build: $ cmake --build . --target myexe --config Release -The ``--config`` option has no effect if the generator -generates a buildsystem specific to a configuration which -is chosen when invoking cmake with the -:variable:`CMAKE_BUILD_TYPE` variable. +The :option:`--config <cmake--build --config>` option has no +effect if the generator generates a buildsystem specific +to a configuration which is chosen when invoking cmake +with the :variable:`CMAKE_BUILD_TYPE` variable. Some buildsystems omit details of command lines invoked -during the build. The ``--verbose`` flag can be used to -cause those command lines to be shown: +during the build. The :option:`--verbose <cmake--build --verbose>` +flag can be used to cause those command lines to be shown: .. code-block:: console $ cmake --build . --target myexe --verbose -The ``--build`` mode can also pass particular command -line options to the underlying build tool by listing -them after ``--``. This can be useful to specify -options to the build tool, such as to continue the +The :option:`--build <cmake --build>` mode can also pass +particular command line options to the underlying build +tool by listing them after ``--``. This can be useful +to specify options to the build tool, such as to continue the build after a failed job, where CMake does not provide a high-level user interface. @@ -638,9 +641,9 @@ building the ``foo.i`` target will preprocess both files. Specifying a Build Program -------------------------- -The program invoked by the ``--build`` mode is determined -by the :variable:`CMAKE_MAKE_PROGRAM` variable. For most -generators, the particular program does not need to be +The program invoked by the :option:`--build <cmake --build>` +mode is determined by the :variable:`CMAKE_MAKE_PROGRAM` variable. +For most generators, the particular program does not need to be configured. ===================== =========================== =========================== @@ -661,7 +664,8 @@ The ``jom`` tool is capable of reading makefiles of the ``NMake`` flavor and building in parallel, while the ``nmake`` tool always builds serially. After generating with the :generator:`NMake Makefiles` generator a user -can run ``jom`` instead of ``nmake``. The ``--build`` +can run ``jom`` instead of ``nmake``. The +:option:`--build <cmake --build>` mode would also use ``jom`` if the :variable:`CMAKE_MAKE_PROGRAM` was set to ``jom`` while using the :generator:`NMake Makefiles` generator, and @@ -671,7 +675,7 @@ and use it as the :variable:`CMAKE_MAKE_PROGRAM`. For completeness, ``nmake`` is an alternative tool which can process the output of the :generator:`NMake Makefiles JOM` generator, but doing -so would be a pessimisation. +so would be a pessimization. Software Installation ===================== @@ -745,8 +749,8 @@ run only tests without ``Qt`` in their name: $ ctest -E Qt -Tests can be run in parallel by passing ``-j`` arguments -to :manual:`ctest(1)`: +Tests can be run in parallel by passing :option:`-j <ctest -j>` +arguments to :manual:`ctest(1)`: .. code-block:: console @@ -754,14 +758,15 @@ to :manual:`ctest(1)`: The environment variable :envvar:`CTEST_PARALLEL_LEVEL` can alternatively be set to avoid the need to pass -``-j``. +:option:`-j <ctest -j>`. By default :manual:`ctest(1)` does not print the output -from the tests. The command line argument ``-V`` (or -``--verbose``) enables verbose mode to print the +from the tests. The command line argument :option:`-V <ctest -V>` +(or ``--verbose``) enables verbose mode to print the output from all tests. -The ``--output-on-failure`` option prints the test -output for failing tests only. The environment variable -:envvar:`CTEST_OUTPUT_ON_FAILURE` +The :option:`--output-on-failure <ctest --output-on-failure>` +option prints the test output for failing tests only. +The environment variable :envvar:`CTEST_OUTPUT_ON_FAILURE` can be set to ``1`` as an alternative to passing the -``--output-on-failure`` option to :manual:`ctest(1)`. +:option:`--output-on-failure <ctest --output-on-failure>` +option to :manual:`ctest(1)`. diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt index 8e23b77..94adac8 100644 --- a/Help/manual/OPTIONS_BUILD.txt +++ b/Help/manual/OPTIONS_BUILD.txt @@ -1,12 +1,15 @@ -``-S <path-to-source>`` +.. option:: -S <path-to-source> + Path to root directory of the CMake project to build. -``-B <path-to-build>`` +.. option:: -B <path-to-build> + Path to directory which CMake will use as the root of build directory. If the directory doesn't already exist CMake will make it. -``-C <initial-cache>`` +.. option:: -C <initial-cache> + Pre-load a script to populate the cache. When CMake is first run in an empty build tree, it creates a @@ -21,7 +24,8 @@ References to :variable:`CMAKE_SOURCE_DIR` and :variable:`CMAKE_BINARY_DIR` within the script evaluate to the top-level source and build tree. -``-D <var>:<type>=<value>, -D <var>=<value>`` +.. option:: -D <var>:<type>=<value>, -D <var>=<value> + Create or update a CMake ``CACHE`` entry. When CMake is first run in an empty build tree, it creates a @@ -41,7 +45,27 @@ This option may also be given as a single argument: ``-D<var>:<type>=<value>`` or ``-D<var>=<value>``. -``-U <globbing_expr>`` + It's important to note that the order of ``-C`` and ``-D`` arguments is + significant. They will be carried out in the order they are listed, with the + last argument taking precedence over the previous ones. For example, if you + specify ``-DCMAKE_BUILD_TYPE=Debug``, followed by a ``-C`` argument with a + file that calls: + + .. code-block:: cmake + + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE) + + then the ``-C`` argument will take precedence, and ``CMAKE_BUILD_TYPE`` will + be set to ``Release``. However, if the ``-D`` argument comes after the ``-C`` + argument, it will be set to ``Debug``. + + If a ``set(... CACHE ...)`` call in the ``-C`` file does not use ``FORCE``, + and a ``-D`` argument sets the same variable, the ``-D`` argument will take + precedence regardless of order because of the nature of non-``FORCE`` + ``set(... CACHE ...)`` calls. + +.. option:: -U <globbing_expr> + Remove matching entries from CMake ``CACHE``. This option may be used to remove one or more variables from the @@ -51,7 +75,8 @@ Use with care, you can make your ``CMakeCache.txt`` non-working. -``-G <generator-name>`` +.. option:: -G <generator-name> + Specify a build system generator. CMake may support multiple native build systems on certain @@ -62,73 +87,85 @@ If not specified, CMake checks the :envvar:`CMAKE_GENERATOR` environment variable and otherwise falls back to a builtin default selection. -``-T <toolset-spec>`` +.. option:: -T <toolset-spec> + Toolset specification for the generator, if supported. Some CMake generators support a toolset specification to tell the native build system how to choose a compiler. See the :variable:`CMAKE_GENERATOR_TOOLSET` variable for details. -``-A <platform-name>`` +.. option:: -A <platform-name> + Specify platform name if supported by generator. Some CMake generators support a platform name to be given to the native build system to choose a compiler or SDK. See the :variable:`CMAKE_GENERATOR_PLATFORM` variable for details. -``--toolchain <path-to-file>`` +.. option:: --toolchain <path-to-file> + Specify the cross compiling toolchain file, equivalent to setting :variable:`CMAKE_TOOLCHAIN_FILE` variable. -``--install-prefix <directory>`` +.. option:: --install-prefix <directory> + Specify the installation directory, used by the :variable:`CMAKE_INSTALL_PREFIX` variable. Must be an absolute path. -``-Wno-dev`` +.. option:: -Wno-dev + Suppress developer warnings. Suppress warnings that are meant for the author of the ``CMakeLists.txt`` files. By default this will also turn off deprecation warnings. -``-Wdev`` +.. option:: -Wdev + Enable developer warnings. Enable warnings that are meant for the author of the ``CMakeLists.txt`` files. By default this will also turn on deprecation warnings. -``-Werror=dev`` - Make developer warnings errors. - - Make warnings that are meant for the author of the ``CMakeLists.txt`` files - errors. By default this will also turn on deprecated warnings as errors. +.. option:: -Wdeprecated -``-Wno-error=dev`` - Make developer warnings not errors. - - Make warnings that are meant for the author of the ``CMakeLists.txt`` files not - errors. By default this will also turn off deprecated warnings as errors. - -``-Wdeprecated`` Enable deprecated functionality warnings. Enable warnings for usage of deprecated functionality, that are meant for the author of the ``CMakeLists.txt`` files. -``-Wno-deprecated`` +.. option:: -Wno-deprecated + Suppress deprecated functionality warnings. Suppress warnings for usage of deprecated functionality, that are meant for the author of the ``CMakeLists.txt`` files. -``-Werror=deprecated`` - Make deprecated macro and function warnings errors. +.. option:: -Werror=<what> + + Treat CMake warnings as errors. ``<what>`` must be one of the following: + + ``dev`` + Make developer warnings errors. + + Make warnings that are meant for the author of the ``CMakeLists.txt`` files + errors. By default this will also turn on deprecated warnings as errors. + + ``deprecated`` + Make deprecated macro and function warnings errors. + + Make warnings for usage of deprecated macros and functions, that are meant + for the author of the ``CMakeLists.txt`` files, errors. + +.. option:: -Wno-error=<what> - Make warnings for usage of deprecated macros and functions, that are meant - for the author of the ``CMakeLists.txt`` files, errors. + Do not treat CMake warnings as errors. ``<what>`` must be one of the following: -``-Wno-error=deprecated`` - Make deprecated macro and function warnings not errors. + ``dev`` + Make warnings that are meant for the author of the ``CMakeLists.txt`` files not + errors. By default this will also turn off deprecated warnings as errors. - Make warnings for usage of deprecated macros and functions, that are meant - for the author of the ``CMakeLists.txt`` files, not errors. + ``deprecated`` + Make warnings for usage of deprecated macros and functions, that are meant + for the author of the ``CMakeLists.txt`` files, not errors. diff --git a/Help/manual/OPTIONS_HELP.txt b/Help/manual/OPTIONS_HELP.txt index feeca7d..78ee245 100644 --- a/Help/manual/OPTIONS_HELP.txt +++ b/Help/manual/OPTIONS_HELP.txt @@ -1,134 +1,152 @@ -.. |file| replace:: The help is printed to a named <f>ile if given. +.. |file| replace:: The output is printed to a named ``<file>`` if given. + +.. option:: -version [<file>], --version [<file>], /V [<file>] + + Show program name/version banner and exit. + |file| + +.. option:: -h, -H, --help, -help, -usage, /? -``--help,-help,-usage,-h,-H,/?`` Print usage information and exit. Usage describes the basic command line interface and its options. -``--version,-version,/V [<f>]`` - Show program name/version banner and exit. +.. option:: --help-full [<file>] - If a file is specified, the version is written into it. - |file| - -``--help-full [<f>]`` Print all help manuals and exit. All manuals are printed in a human-readable text format. |file| -``--help-manual <man> [<f>]`` +.. option:: --help-manual <man> [<file>] + Print one help manual and exit. The specified manual is printed in a human-readable text format. |file| -``--help-manual-list [<f>]`` +.. option:: --help-manual-list [<file>] + List help manuals available and exit. The list contains all manuals for which help may be obtained by using the ``--help-manual`` option followed by a manual name. |file| -``--help-command <cmd> [<f>]`` +.. option:: --help-command <cmd> [<file>] + Print help for one command and exit. The :manual:`cmake-commands(7)` manual entry for ``<cmd>`` is printed in a human-readable text format. |file| -``--help-command-list [<f>]`` +.. option:: --help-command-list [<file>] + List commands with help available and exit. The list contains all commands for which help may be obtained by using the ``--help-command`` option followed by a command name. |file| -``--help-commands [<f>]`` +.. option:: --help-commands [<file>] + Print cmake-commands manual and exit. The :manual:`cmake-commands(7)` manual is printed in a human-readable text format. |file| -``--help-module <mod> [<f>]`` +.. option:: --help-module <mod> [<file>] + Print help for one module and exit. The :manual:`cmake-modules(7)` manual entry for ``<mod>`` is printed in a human-readable text format. |file| -``--help-module-list [<f>]`` +.. option:: --help-module-list [<file>] + List modules with help available and exit. The list contains all modules for which help may be obtained by using the ``--help-module`` option followed by a module name. |file| -``--help-modules [<f>]`` +.. option:: --help-modules [<file>] + Print cmake-modules manual and exit. The :manual:`cmake-modules(7)` manual is printed in a human-readable text format. |file| -``--help-policy <cmp> [<f>]`` +.. option:: --help-policy <cmp> [<file>] + Print help for one policy and exit. The :manual:`cmake-policies(7)` manual entry for ``<cmp>`` is printed in a human-readable text format. |file| -``--help-policy-list [<f>]`` +.. option:: --help-policy-list [<file>] + List policies with help available and exit. The list contains all policies for which help may be obtained by using the ``--help-policy`` option followed by a policy name. |file| -``--help-policies [<f>]`` +.. option:: --help-policies [<file>] + Print cmake-policies manual and exit. The :manual:`cmake-policies(7)` manual is printed in a human-readable text format. |file| -``--help-property <prop> [<f>]`` +.. option:: --help-property <prop> [<file>] + Print help for one property and exit. The :manual:`cmake-properties(7)` manual entries for ``<prop>`` are printed in a human-readable text format. |file| -``--help-property-list [<f>]`` +.. option:: --help-property-list [<file>] + List properties with help available and exit. The list contains all properties for which help may be obtained by using the ``--help-property`` option followed by a property name. |file| -``--help-properties [<f>]`` +.. option:: --help-properties [<file>] + Print cmake-properties manual and exit. The :manual:`cmake-properties(7)` manual is printed in a human-readable text format. |file| -``--help-variable <var> [<f>]`` +.. option:: --help-variable <var> [<file>] + Print help for one variable and exit. The :manual:`cmake-variables(7)` manual entry for ``<var>`` is printed in a human-readable text format. |file| -``--help-variable-list [<f>]`` +.. option:: --help-variable-list [<file>] + List variables with help available and exit. The list contains all variables for which help may be obtained by using the ``--help-variable`` option followed by a variable name. |file| -``--help-variables [<f>]`` +.. option:: --help-variables [<file>] + Print cmake-variables manual and exit. The :manual:`cmake-variables(7)` manual is printed in a diff --git a/Help/manual/ccmake.1.rst b/Help/manual/ccmake.1.rst index 60d45a3..cd66d51 100644 --- a/Help/manual/ccmake.1.rst +++ b/Help/manual/ccmake.1.rst @@ -8,7 +8,7 @@ Synopsis .. parsed-literal:: - ccmake [<options>] {<path-to-source> | <path-to-existing-build>} + ccmake [<options>] <path-to-source | path-to-existing-build> Description =========== @@ -27,6 +27,8 @@ native tool on their platform. Options ======= +.. program:: ccmake + .. include:: OPTIONS_BUILD.txt .. include:: OPTIONS_HELP.txt diff --git a/Help/manual/cmake-buildsystem.7.rst b/Help/manual/cmake-buildsystem.7.rst index bceff2d..b14160c 100644 --- a/Help/manual/cmake-buildsystem.7.rst +++ b/Help/manual/cmake-buildsystem.7.rst @@ -257,7 +257,7 @@ targets in multiple different directories convenient through use of the Transitive Usage Requirements ----------------------------- -The usage requirements of a target can transitively propagate to dependents. +The usage requirements of a target can transitively propagate to the dependents. The :command:`target_link_libraries` command has ``PRIVATE``, ``INTERFACE`` and ``PUBLIC`` keywords to control the propagation. @@ -279,8 +279,10 @@ The :command:`target_link_libraries` command has ``PRIVATE``, # consumer is compiled with -DUSING_ARCHIVE_LIB target_link_libraries(consumer archiveExtras) -Because ``archive`` is a ``PUBLIC`` dependency of ``archiveExtras``, the -usage requirements of it are propagated to ``consumer`` too. Because +Because the ``archive`` is a ``PUBLIC`` dependency of ``archiveExtras``, the +usage requirements of it are propagated to ``consumer`` too. + +Because ``serialization`` is a ``PRIVATE`` dependency of ``archiveExtras``, the usage requirements of it are not propagated to ``consumer``. diff --git a/Help/manual/cmake-commands.7.rst b/Help/manual/cmake-commands.7.rst index 036fa8f..0f35632 100644 --- a/Help/manual/cmake-commands.7.rst +++ b/Help/manual/cmake-commands.7.rst @@ -15,6 +15,7 @@ These commands are always available. .. toctree:: :maxdepth: 1 + /command/block /command/break /command/cmake_host_system_information /command/cmake_language @@ -26,6 +27,7 @@ These commands are always available. /command/continue /command/else /command/elseif + /command/endblock /command/endforeach /command/endfunction /command/endif diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst index 737b22c..50fcf75 100644 --- a/Help/manual/cmake-env-variables.7.rst +++ b/Help/manual/cmake-env-variables.7.rst @@ -21,6 +21,8 @@ Environment Variables that Change Behavior :maxdepth: 1 /envvar/CMAKE_PREFIX_PATH + /envvar/SSL_CERT_DIR + /envvar/SSL_CERT_FILE Environment Variables that Control the Build ============================================ diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst index 7a6188a..69e3f20 100644 --- a/Help/manual/cmake-generator-expressions.7.rst +++ b/Help/manual/cmake-generator-expressions.7.rst @@ -594,6 +594,10 @@ Configuration Expressions expression when it is evaluated on a property of an :prop_tgt:`IMPORTED` target. + .. versionchanged:: 3.19 + Multiple configurations can be specified for ``cfgs``. + CMake 3.18 and earlier only accepted a single configuration. + .. genex:: $<OUTPUT_CONFIG:...> .. versionadded:: 3.20 @@ -627,9 +631,8 @@ Platform .. genex:: $<PLATFORM_ID:platform_ids> - where ``platform_ids`` is a comma-separated list. ``1`` if CMake's platform id matches any one of the entries in - ``platform_ids``, otherwise ``0``. + comma-separated list ``platform_ids``, otherwise ``0``. See also the :variable:`CMAKE_SYSTEM_NAME` variable. Compiler Version @@ -844,10 +847,15 @@ related to most of the expressions in this sub-section. .. versionadded:: 3.3 - ``1`` when the language used for compilation unit matches any of the entries - in ``languages``, otherwise ``0``. This expression may be used to specify - compile options, compile definitions, and include directories for source - files of a particular language in a target. For example: + .. versionchanged:: 3.15 + Multiple languages can be specified for ``languages``. + CMake 3.14 and earlier only accepted a single language. + + ``1`` when the language used for compilation unit matches any of the + comma-separated entries in ``languages``, otherwise ``0``. This expression + may be used to specify compile options, compile definitions, and include + directories for source files of a particular language in a target. For + example: .. code-block:: cmake @@ -892,8 +900,8 @@ related to most of the expressions in this sub-section. ``1`` when the language used for compilation unit matches ``language`` and CMake's compiler id of the ``language`` compiler matches any one of the - entries in ``compiler_ids``, otherwise ``0``. This expression is a short form - for the combination of ``$<COMPILE_LANGUAGE:language>`` and + comma-separated entries in ``compiler_ids``, otherwise ``0``. This expression + is a short form for the combination of ``$<COMPILE_LANGUAGE:language>`` and ``$<LANG_COMPILER_ID:compiler_ids>``. This expression may be used to specify compile options, compile definitions, and include directories for source files of a particular language and compiler combination in a target. @@ -967,10 +975,10 @@ Linker Language And ID .. versionadded:: 3.18 - ``1`` when the language used for link step matches any of the entries - in ``languages``, otherwise ``0``. This expression may be used to specify - link libraries, link options, link directories and link dependencies of a - particular language in a target. For example: + ``1`` when the language used for link step matches any of the comma-separated + entries in ``languages``, otherwise ``0``. This expression may be used to + specify link libraries, link options, link directories and link dependencies + of a particular language in a target. For example: .. code-block:: cmake @@ -1033,9 +1041,9 @@ Linker Language And ID .. versionadded:: 3.18 ``1`` when the language used for link step matches ``language`` and the - CMake's compiler id of the language linker matches any one of the entries - in ``compiler_ids``, otherwise ``0``. This expression is a short form for the - combination of ``$<LINK_LANGUAGE:language>`` and + CMake's compiler id of the language linker matches any one of the comma-separated + entries in ``compiler_ids``, otherwise ``0``. This expression is a short form + for the combination of ``$<LINK_LANGUAGE:language>`` and ``$<LANG_COMPILER_ID:compiler_ids>``. This expression may be used to specify link libraries, link options, link directories and link dependencies of a particular language and linker combination in a target. For example: diff --git a/Help/manual/cmake-generators.7.rst b/Help/manual/cmake-generators.7.rst index 034e218..ed5bbbf 100644 --- a/Help/manual/cmake-generators.7.rst +++ b/Help/manual/cmake-generators.7.rst @@ -18,11 +18,11 @@ as a variant of some of the `Command-Line Build Tool Generators`_ to produce project files for an auxiliary IDE. CMake Generators are platform-specific so each may be available only -on certain platforms. The :manual:`cmake(1)` command-line tool ``--help`` -output lists available generators on the current platform. Use its ``-G`` -option to specify the generator for a new build tree. -The :manual:`cmake-gui(1)` offers interactive selection of a generator -when creating a new build tree. +on certain platforms. The :manual:`cmake(1)` command-line tool +:option:`--help <cmake --help>` output lists available generators on the +current platform. Use its :option:`-G <cmake -G>` option to specify the +generator for a new build tree. The :manual:`cmake-gui(1)` offers +interactive selection of a generator when creating a new build tree. CMake Generators ================ @@ -108,9 +108,9 @@ Extra Generators ================ Some of the `CMake Generators`_ listed in the :manual:`cmake(1)` -command-line tool ``--help`` output may have variants that specify -an extra generator for an auxiliary IDE tool. Such generator -names have the form ``<extra-generator> - <main-generator>``. +command-line tool :option:`--help <cmake --help>` output may have +variants that specify an extra generator for an auxiliary IDE tool. +Such generator names have the form ``<extra-generator> - <main-generator>``. The following extra generators are known to CMake. .. toctree:: diff --git a/Help/manual/cmake-gui.1.rst b/Help/manual/cmake-gui.1.rst index 281986f..dd0eeca 100644 --- a/Help/manual/cmake-gui.1.rst +++ b/Help/manual/cmake-gui.1.rst @@ -9,7 +9,7 @@ Synopsis .. parsed-literal:: cmake-gui [<options>] - cmake-gui [<options>] {<path-to-source> | <path-to-existing-build>} + cmake-gui [<options>] <path-to-source | path-to-existing-build> cmake-gui [<options>] -S <path-to-source> -B <path-to-build> cmake-gui [<options>] --browse-manual @@ -29,19 +29,25 @@ native tool on their platform. Options ======= -``-S <path-to-source>`` +.. program:: cmake-gui + +.. option:: -S <path-to-source> + Path to root directory of the CMake project to build. -``-B <path-to-build>`` +.. option:: -B <path-to-build> + Path to directory which CMake will use as the root of build directory. If the directory doesn't already exist CMake will make it. -``--preset=<preset-name>`` +.. option:: --preset=<preset-name> + Name of the preset to use from the project's :manual:`presets <cmake-presets(7)>` files, if it has them. -``--browse-manual`` +.. option:: --browse-manual + Open the CMake reference manual in a browser and immediately exit. .. include:: OPTIONS_HELP.txt diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 93beea9..d161a28 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -193,6 +193,7 @@ They are normally called through the :command:`find_package` command. /module/FindOpenGL /module/FindOpenMP /module/FindOpenSceneGraph + /module/FindOpenSP /module/FindOpenSSL /module/FindOpenThreads /module/Findosg @@ -236,6 +237,7 @@ They are normally called through the :command:`find_package` command. /module/FindRuby /module/FindSDL /module/FindSDL_image + /module/FindSDL_gfx /module/FindSDL_mixer /module/FindSDL_net /module/FindSDL_sound diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index f6ab0c7..d6a30ff 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -52,6 +52,16 @@ to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.25 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0142: The Xcode generator does not append per-config suffixes to library search paths. </policy/CMP0142> + CMP0141: MSVC debug information format flags are selected by an abstraction. </policy/CMP0141> + CMP0140: The return() command checks its arguments. </policy/CMP0140> + Policies Introduced by CMake 3.24 ================================= diff --git a/Help/manual/cmake-presets.7.rst b/Help/manual/cmake-presets.7.rst index a96c704..ae6dcb1 100644 --- a/Help/manual/cmake-presets.7.rst +++ b/Help/manual/cmake-presets.7.rst @@ -10,6 +10,8 @@ cmake-presets(7) Introduction ============ +.. versionadded:: 3.19 + One problem that CMake users often face is sharing settings with other people for common ways to configure a project. This may be done to support CI builds, or for users who frequently use the same build. CMake supports two main files, @@ -19,10 +21,10 @@ supports files included with the ``include`` field. ``CMakePresets.json`` and ``CMakeUserPresets.json`` live in the project's root directory. They both have exactly the same format, and both are optional -(though at least one must be present if ``--preset`` is specified). -``CMakePresets.json`` is meant to specify project-wide build details, while -``CMakeUserPresets.json`` is meant for developers to specify their own local -build details. +(though at least one must be present if :option:`--preset <cmake --preset>` +is specified). ``CMakePresets.json`` is meant to specify project-wide build +details, while ``CMakeUserPresets.json`` is meant for developers to specify +their own local build details. ``CMakePresets.json`` may be checked into a version control system, and ``CMakeUserPresets.json`` should NOT be checked in. For example, if a @@ -40,7 +42,6 @@ The files are a JSON document with an object as the root: The root object recognizes the following fields: ``version`` - A required integer representing the version of the JSON schema. The supported versions are: @@ -59,32 +60,29 @@ The root object recognizes the following fields: ``5`` .. versionadded:: 3.24 -``cmakeMinimumRequired`` + ``6`` + .. versionadded:: 3.25 +``cmakeMinimumRequired`` An optional object representing the minimum version of CMake needed to build this project. This object consists of the following fields: ``major`` - An optional integer representing the major version. ``minor`` - An optional integer representing the minor version. ``patch`` - An optional integer representing the patch version. ``include`` - An optional array of strings representing files to include. If the filenames are not absolute, they are considered relative to the current file. This is allowed in preset files specifying version ``4`` or above. See `Includes`_ for discussion of the constraints on included files. ``vendor`` - An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, the keys should be a vendor-specific domain name @@ -93,20 +91,25 @@ The root object recognizes the following fields: desired by the vendor, though will typically be a map. ``configurePresets`` - An optional array of `Configure Preset`_ objects. This is allowed in preset files specifying version ``1`` or above. ``buildPresets`` - An optional array of `Build Preset`_ objects. This is allowed in preset files specifying version ``2`` or above. ``testPresets`` - An optional array of `Test Preset`_ objects. This is allowed in preset files specifying version ``2`` or above. +``packagePresets`` + An optional array of `Package Preset`_ objects. + This is allowed in preset files specifying version ``6`` or above. + +``workflowPresets`` + An optional array of `Workflow Preset`_ objects. + This is allowed in preset files specifying version ``6`` or above. + Includes ^^^^^^^^ @@ -134,15 +137,14 @@ Each entry of the ``configurePresets`` array is a JSON object that may contain the following fields: ``name`` - A required string representing the machine-friendly name of the preset. This identifier is used in the :ref:`cmake --preset <CMake Options>` option. There must not be two configure presets in the union of ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same directory with the same name. - However, a configure preset may have the same name as a build or test preset. + However, a configure preset may have the same name as a build, test, + package, or workflow preset. ``hidden`` - An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the ``--preset=`` argument, will not show up in the :manual:`CMake GUI <cmake-gui(1)>`, and does not @@ -151,7 +153,6 @@ that may contain the following fields: other presets to inherit via the ``inherits`` field. ``inherits`` - An optional array of strings representing the names of presets to inherit from. This field can also be a string, which is equivalent to an array containing one string. @@ -169,12 +170,10 @@ that may contain the following fields: ``CMakeUserPresets.json``. ``condition`` - An optional `Condition`_ object. This is allowed in preset files specifying version ``3`` or above. ``vendor`` - An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the @@ -183,47 +182,43 @@ that may contain the following fields: when appropriate. ``displayName`` - An optional string with a human-friendly name of the preset. ``description`` - An optional string with a human-friendly description of the preset. ``generator`` - An optional string representing the generator to use for the preset. If ``generator`` is not specified, it must be inherited from the ``inherits`` preset (unless this preset is ``hidden``). In version ``3`` or above, this field may be omitted to fall back to regular generator discovery procedure. - Note that for Visual Studio generators, unlike in the command line ``-G`` - argument, you cannot include the platform name in the generator name. Use - the ``architecture`` field instead. + Note that for Visual Studio generators, unlike in the command line + :option:`-G <cmake -G>` argument, you cannot include the platform name + in the generator name. Use the ``architecture`` field instead. ``architecture``, ``toolset`` - Optional fields representing the platform and toolset, respectively, for - generators that support them. Each may be either a string or an object - with the following fields: + :manual:`generators <cmake-generators(7)>` that support them. - ``value`` + See :option:`cmake -A` option for for possible values for ``architecture`` + and :option:`cmake -T` for ``toolset``. + + Each may be either a string or an object with the following fields: + ``value`` An optional string representing the value. ``strategy`` - An optional string telling CMake how to handle the ``architecture`` or ``toolset`` field. Valid values are: ``"set"`` - Set the respective value. This will result in an error for generators that do not support the respective field. ``"external"`` - Do not set the value, even if the generator supports it. This is useful if, for example, a preset uses the Ninja generator, and an IDE knows how to set up the Visual C++ environment from the @@ -232,7 +227,6 @@ that may contain the following fields: before invoking CMake. ``toolchainFile`` - An optional string representing the path to the toolchain file. This field supports `macro expansion`_. If a relative path is specified, it is calculated relative to the build directory, and if not found, @@ -241,7 +235,6 @@ that may contain the following fields: specifying version ``3`` or above. ``binaryDir`` - An optional string representing the path to the output binary directory. This field supports `macro expansion`_. If a relative path is specified, it is calculated relative to the source directory. If ``binaryDir`` is not @@ -250,20 +243,17 @@ that may contain the following fields: omitted. ``installDir`` - An optional string representing the path to the installation directory. This field supports `macro expansion`_. If a relative path is specified, it is calculated relative to the source directory. This is allowed in preset files specifying version ``3`` or above. ``cmakeExecutable`` - An optional string representing the path to the CMake executable to use for this preset. This is reserved for use by IDEs, and is not used by CMake itself. IDEs that use this field should expand any macros in it. ``cacheVariables`` - An optional map of cache variables. The key is the variable name (which may not be an empty string), and the value is either ``null``, a boolean (which is equivalent to a value of ``"TRUE"`` or ``"FALSE"`` and a type @@ -271,11 +261,9 @@ that may contain the following fields: supports `macro expansion`_), or an object with the following fields: ``type`` - An optional string representing the type of the variable. ``value`` - A required string or boolean representing the value of the variable. A boolean is equivalent to ``"TRUE"`` or ``"FALSE"``. This field supports `macro expansion`_. @@ -288,7 +276,6 @@ that may contain the following fields: a value was inherited from another preset. ``environment`` - An optional map of environment variables. The key is the variable name (which may not be an empty string), and the value is either ``null`` or a string representing the value of the variable. Each variable is set @@ -306,73 +293,68 @@ that may contain the following fields: a value was inherited from another preset. ``warnings`` - An optional object specifying the warnings to enable. The object may contain the following fields: ``dev`` - - An optional boolean. Equivalent to passing ``-Wdev`` or ``-Wno-dev`` - on the command line. This may not be set to ``false`` if ``errors.dev`` - is set to ``true``. + An optional boolean. Equivalent to passing :option:`-Wdev <cmake -Wdev>` + or :option:`-Wno-dev <cmake -Wno-dev>` on the command line. This may not + be set to ``false`` if ``errors.dev`` is set to ``true``. ``deprecated`` - - An optional boolean. Equivalent to passing ``-Wdeprecated`` or - ``-Wno-deprecated`` on the command line. This may not be set to - ``false`` if ``errors.deprecated`` is set to ``true``. + An optional boolean. Equivalent to passing + :option:`-Wdeprecated <cmake -Wdeprecated>` or + :option:`-Wno-deprecated <cmake -Wno-deprecated>` on the command line. + This may not be set to ``false`` if ``errors.deprecated`` is set to + ``true``. ``uninitialized`` - An optional boolean. Setting this to ``true`` is equivalent to passing - ``--warn-uninitialized`` on the command line. + :option:`--warn-uninitialized <cmake --warn-uninitialized>` on the command + line. ``unusedCli`` - An optional boolean. Setting this to ``false`` is equivalent to passing - ``--no-warn-unused-cli`` on the command line. + :option:`--no-warn-unused-cli <cmake --no-warn-unused-cli>` on the command + line. ``systemVars`` - An optional boolean. Setting this to ``true`` is equivalent to passing - ``--check-system-vars`` on the command line. + :option:`--check-system-vars <cmake --check-system-vars>` on the command + line. ``errors`` - An optional object specifying the errors to enable. The object may contain the following fields: ``dev`` - - An optional boolean. Equivalent to passing ``-Werror=dev`` or - ``-Wno-error=dev`` on the command line. This may not be set to ``true`` - if ``warnings.dev`` is set to ``false``. + An optional boolean. Equivalent to passing :option:`-Werror=dev <cmake -Werror>` + or :option:`-Wno-error=dev <cmake -Werror>` on the command line. + This may not be set to ``true`` if ``warnings.dev`` is set to ``false``. ``deprecated`` - - An optional boolean. Equivalent to passing ``-Werror=deprecated`` or - ``-Wno-error=deprecated`` on the command line. This may not be set to - ``true`` if ``warnings.deprecated`` is set to ``false``. + An optional boolean. Equivalent to passing + :option:`-Werror=deprecated <cmake -Werror>` or + :option:`-Wno-error=deprecated <cmake -Werror>` on the command line. + This may not be set to ``true`` if ``warnings.deprecated`` is set to + ``false``. ``debug`` - An optional object specifying debug options. The object may contain the following fields: ``output`` - An optional boolean. Setting this to ``true`` is equivalent to passing - ``--debug-output`` on the command line. + :option:`--debug-output <cmake --debug-output>` on the command line. ``tryCompile`` - An optional boolean. Setting this to ``true`` is equivalent to passing - ``--debug-trycompile`` on the command line. + :option:`--debug-trycompile <cmake --debug-trycompile>` on the command + line. ``find`` - An optional boolean. Setting this to ``true`` is equivalent to passing - ``--debug-find`` on the command line. + :option:`--debug-find <cmake --debug-find>` on the command line. Build Preset ^^^^^^^^^^^^ @@ -381,24 +363,23 @@ Each entry of the ``buildPresets`` array is a JSON object that may contain the following fields: ``name`` - A required string representing the machine-friendly name of the preset. This identifier is used in the :ref:`cmake --build --preset <Build Tool Mode>` option. There must not be two build presets in the union of ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same directory with the same name. - However, a build preset may have the same name as a configure or test preset. + However, a build preset may have the same name as a configure, test, + package, or workflow preset. ``hidden`` - An optional boolean specifying whether or not a preset should be hidden. - If a preset is hidden, it cannot be used in the ``--preset`` argument + If a preset is hidden, it cannot be used in the + :option:`--preset <cmake --preset>` argument and does not have to have a valid ``configurePreset``, even from inheritance. ``hidden`` presets are intended to be used as a base for other presets to inherit via the ``inherits`` field. ``inherits`` - An optional array of strings representing the names of presets to inherit from. This field can also be a string, which is equivalent to an array containing one string. @@ -416,12 +397,10 @@ that may contain the following fields: ``CMakeUserPresets.json``. ``condition`` - An optional `Condition`_ object. This is allowed in preset files specifying version ``3`` or above. ``vendor`` - An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the @@ -430,15 +409,12 @@ that may contain the following fields: when appropriate. ``displayName`` - An optional string with a human-friendly name of the preset. ``description`` - An optional string with a human-friendly description of the preset. ``environment`` - An optional map of environment variables. The key is the variable name (which may not be an empty string), and the value is either ``null`` or a string representing the value of the variable. Each variable is set @@ -469,7 +445,6 @@ that may contain the following fields: project. ``configurePreset`` - An optional string specifying the name of a configure preset to associate with this build preset. If ``configurePreset`` is not specified, it must be inherited from the inherits preset (unless this @@ -478,36 +453,30 @@ that may contain the following fields: configuration did. ``inheritConfigureEnvironment`` - An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited build preset environments, but before environment variables explicitly specified in this build preset. ``jobs`` - - An optional integer. Equivalent to passing ``--parallel`` or ``-j`` on - the command line. + An optional integer. Equivalent to passing + :option:`--parallel <cmake--build --parallel>` or ``-j`` on the command line. ``targets`` - An optional string or array of strings. Equivalent to passing - ``--target`` or ``-t`` on the command line. Vendors may ignore the - targets property or hide build presets that explicitly specify targets. - This field supports macro expansion. + :option:`--target <cmake--build --target>` or ``-t`` on the command line. + Vendors may ignore the targets property or hide build presets that + explicitly specify targets. This field supports macro expansion. ``configuration`` - - An optional string. Equivalent to passing ``--config`` on the command - line. + An optional string. Equivalent to passing + :option:`--config <cmake--build --config>` on the command line. ``cleanFirst`` - - An optional bool. If true, equivalent to passing ``--clean-first`` on - the command line. + An optional bool. If true, equivalent to passing + :option:`--clean-first <cmake--build --clean-first>` on the command line. ``resolvePackageReferences`` - An optional string that specifies the package resolve mode. This is allowed in preset files specifying version ``4`` or above. @@ -517,24 +486,23 @@ that may contain the following fields: package references, this option does nothing. Valid values are: ``on`` - Causes package references to be resolved before attempting a build. ``off`` - Package references will not be resolved. Note that this may cause errors in some build environments, such as .NET SDK style projects. ``only`` - Only resolve package references, but do not perform a build. .. note:: - The command line parameter ``--resolve-package-references`` will take - priority over this setting. If the command line parameter is not provided - and this setting is not specified, an environment-specific cache variable - will be evaluated to decide, if package restoration should be performed. + The command line parameter + :option:`--resolve-package-references <cmake--build --resolve-package-references>` + will take priority over this setting. If the command line parameter is not + provided and this setting is not specified, an environment-specific cache + variable will be evaluated to decide, if package restoration should be + performed. When using the Visual Studio generator, package references are defined using the :prop_tgt:`VS_PACKAGE_REFERENCES` property. Package references @@ -543,12 +511,10 @@ that may contain the following fields: done from within a configure preset. ``verbose`` - - An optional bool. If true, equivalent to passing ``--verbose`` on the - command line. + An optional bool. If true, equivalent to passing + :option:`--verbose <cmake--build --verbose>` on the command line. ``nativeToolOptions`` - An optional array of strings. Equivalent to passing options after ``--`` on the command line. The array values support macro expansion. @@ -559,23 +525,22 @@ Each entry of the ``testPresets`` array is a JSON object that may contain the following fields: ``name`` - A required string representing the machine-friendly name of the preset. - This identifier is used in the :ref:`ctest --preset <CTest Options>` option. + This identifier is used in the :option:`ctest --preset` option. There must not be two test presets in the union of ``CMakePresets.json`` and ``CMakeUserPresets.json`` in the same directory with the same name. - However, a test preset may have the same name as a configure or build preset. + However, a test preset may have the same name as a configure, build, + package, or workflow preset. ``hidden`` - An optional boolean specifying whether or not a preset should be hidden. - If a preset is hidden, it cannot be used in the ``--preset`` argument + If a preset is hidden, it cannot be used in the + :option:`--preset <ctest --preset>` argument and does not have to have a valid ``configurePreset``, even from inheritance. ``hidden`` presets are intended to be used as a base for other presets to inherit via the ``inherits`` field. ``inherits`` - An optional array of strings representing the names of presets to inherit from. This field can also be a string, which is equivalent to an array containing one string. @@ -593,12 +558,10 @@ that may contain the following fields: ``CMakeUserPresets.json``. ``condition`` - An optional `Condition`_ object. This is allowed in preset files specifying version ``3`` or above. ``vendor`` - An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the @@ -607,15 +570,12 @@ that may contain the following fields: when appropriate. ``displayName`` - An optional string with a human-friendly name of the preset. ``description`` - An optional string with a human-friendly description of the preset. ``environment`` - An optional map of environment variables. The key is the variable name (which may not be an empty string), and the value is either ``null`` or a string representing the value of the variable. Each variable is set @@ -633,7 +593,6 @@ that may contain the following fields: even if a value was inherited from another preset. ``configurePreset`` - An optional string specifying the name of a configure preset to associate with this test preset. If ``configurePreset`` is not specified, it must be inherited from the inherits preset (unless this @@ -642,233 +601,210 @@ that may contain the following fields: configuration did and build did. ``inheritConfigureEnvironment`` - An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited test preset environments, but before environment variables explicitly specified in this test preset. ``configuration`` - - An optional string. Equivalent to passing ``--build-config`` on the - command line. + An optional string. Equivalent to passing + :option:`--build-config <ctest --build-config>` on the command line. ``overwriteConfigurationFile`` - An optional array of configuration options to overwrite options specified in the CTest configuration file. Equivalent to passing - ``--overwrite`` for each value in the array. The array values - support macro expansion. + :option:`--overwrite <ctest --overwrite>` for each value in the array. + The array values support macro expansion. ``output`` - An optional object specifying output options. The object may contain the following fields. ``shortProgress`` - - An optional bool. If true, equivalent to passing ``--progress`` on the - command line. + An optional bool. If true, equivalent to passing + :option:`--progress <ctest --progress>` on the command line. ``verbosity`` - An optional string specifying verbosity level. Must be one of the following: ``default`` - Equivalent to passing no verbosity flags on the command line. ``verbose`` - - Equivalent to passing ``--verbose`` on the command line. + Equivalent to passing :option:`--verbose <ctest --verbose>` on + the command line. ``extra`` - - Equivalent to passing ``--extra-verbose`` on the command line. + Equivalent to passing :option:`--extra-verbose <ctest --extra-verbose>` + on the command line. ``debug`` - - An optional bool. If true, equivalent to passing ``--debug`` on the - command line. + An optional bool. If true, equivalent to passing + :option:`--debug <ctest --debug>` on the command line. ``outputOnFailure`` - An optional bool. If true, equivalent to passing - ``--output-on-failure`` on the command line. + :option:`--output-on-failure <ctest --output-on-failure>` on the command + line. ``quiet`` - - An optional bool. If true, equivalent to passing ``--quiet`` on the - command line. + An optional bool. If true, equivalent to passing + :option:`--quiet <ctest --quiet>` on the command line. ``outputLogFile`` - An optional string specifying a path to a log file. Equivalent to - passing ``--output-log`` on the command line. This field supports - macro expansion. + passing :option:`--output-log <ctest --output-log>` on the command line. + This field supports macro expansion. - ``labelSummary`` + ``outputJUnitFile`` + An optional string specifying a path to a JUnit file. Equivalent to + passing :option:`--output-junit <ctest --output-junit>` on the command line. + This field supports macro expansion. This is allowed in preset files + specifying version ``6`` or above. + ``labelSummary`` An optional bool. If false, equivalent to passing - ``--no-label-summary`` on the command line. + :option:`--no-label-summary <ctest --no-label-summary>` on the command + line. ``subprojectSummary`` - An optional bool. If false, equivalent to passing - ``--no-subproject-summary`` on the command line. + :option:`--no-subproject-summary <ctest --no-subproject-summary>` + on the command line. ``maxPassedTestOutputSize`` - An optional integer specifying the maximum output for passed tests in - bytes. Equivalent to passing ``--test-output-size-passed`` on the - command line. + bytes. Equivalent to passing + :option:`--test-output-size-passed <ctest --test-output-size-passed>` + on the command line. ``maxFailedTestOutputSize`` - An optional integer specifying the maximum output for failed tests in - bytes. Equivalent to passing ``--test-output-size-failed`` on the - command line. + bytes. Equivalent to passing + :option:`--test-output-size-failed <ctest --test-output-size-failed>` + on the command line. ``testOutputTruncation`` - An optional string specifying the test output truncation mode. Equivalent - to passing ``--test-output-truncation`` on the command line." - This is allowed in preset files specifying version ``5`` or above. + to passing + :option:`--test-output-truncation <ctest --test-output-truncation>` on + the command line. This is allowed in preset files specifying version + ``5`` or above. ``maxTestNameWidth`` - An optional integer specifying the maximum width of a test name to - output. Equivalent to passing ``--max-width`` on the command line. + output. Equivalent to passing :option:`--max-width <ctest --max-width>` + on the command line. ``filter`` - An optional object specifying how to filter the tests to run. The object may contain the following fields. ``include`` - An optional object specifying which tests to include. The object may contain the following fields. ``name`` - An optional string specifying a regex for test names. Equivalent to - passing ``--tests-regex`` on the command line. This field supports - macro expansion. CMake regex syntax is described under - :ref:`string(REGEX) <Regex Specification>`. - + passing :option:`--tests-regex <ctest --tests-regex>` on the command + line. This field supports macro expansion. CMake regex syntax is + described under :ref:`string(REGEX) <Regex Specification>`. ``label`` - An optional string specifying a regex for test labels. Equivalent to - passing ``--label-regex`` on the command line. This field supports - macro expansion. + passing :option:`--label-regex <ctest --label-regex>` on the command + line. This field supports macro expansion. ``useUnion`` - - An optional bool. Equivalent to passing ``--union`` on the command - line. + An optional bool. Equivalent to passing :option:`--union <ctest --union>` + on the command line. ``index`` - An optional object specifying tests to include by test index. The object may contain the following fields. Can also be an optional string specifying a file with the command line syntax for - ``--tests-information``. If specified as a string, this field - supports macro expansion. + :option:`--tests-information <ctest --tests-information>`. + If specified as a string, this field supports macro expansion. ``start`` - An optional integer specifying a test index to start testing at. ``end`` - An optional integer specifying a test index to stop testing at. ``stride`` - An optional integer specifying the increment. ``specificTests`` - An optional array of integers specifying specific test indices to run. ``exclude`` - An optional object specifying which tests to exclude. The object may contain the following fields. ``name`` - An optional string specifying a regex for test names. Equivalent to - passing ``--exclude-regex`` on the command line. This field supports - macro expansion. + passing :option:`--exclude-regex <ctest --exclude-regex>` on the + command line. This field supports macro expansion. ``label`` - An optional string specifying a regex for test labels. Equivalent to - passing ``--label-exclude`` on the command line. This field supports - macro expansion. + passing :option:`--label-exclude <ctest --label-exclude>` on the + command line. This field supports macro expansion. ``fixtures`` - An optional object specifying which fixtures to exclude from adding tests. The object may contain the following fields. ``any`` - An optional string specifying a regex for text fixtures to exclude - from adding any tests. Equivalent to ``--fixture-exclude-any`` on + from adding any tests. Equivalent to + :option:`--fixture-exclude-any <ctest --fixture-exclude-any>` on the command line. This field supports macro expansion. ``setup`` - An optional string specifying a regex for text fixtures to exclude - from adding setup tests. Equivalent to ``--fixture-exclude-setup`` + from adding setup tests. Equivalent to + :option:`--fixture-exclude-setup <ctest --fixture-exclude-setup>` on the command line. This field supports macro expansion. ``cleanup`` - An optional string specifying a regex for text fixtures to exclude from adding cleanup tests. Equivalent to - ``--fixture-exclude-cleanup`` on the command line. This field - supports macro expansion. + :option:`--fixture-exclude-cleanup <ctest --fixture-exclude-cleanup>` + on the command line. This field supports macro expansion. ``execution`` - An optional object specifying options for test execution. The object may contain the following fields. ``stopOnFailure`` - - An optional bool. If true, equivalent to passing ``--stop-on-failure`` - on the command line. + An optional bool. If true, equivalent to passing + :option:`--stop-on-failure <ctest --stop-on-failure>` on the command + line. ``enableFailover`` - - An optional bool. If true, equivalent to passing ``-F`` on the command - line. + An optional bool. If true, equivalent to passing :option:`-F <ctest -F>` + on the command line. ``jobs`` - - An optional integer. Equivalent to passing ``--parallel`` on the - command line. + An optional integer. Equivalent to passing + :option:`--parallel <ctest --parallel>` on the command line. ``resourceSpecFile`` - - An optional string. Equivalent to passing ``--resource-spec-file`` on + An optional string. Equivalent to passing + :option:`--resource-spec-file <ctest --resource-spec-file>` on the command line. This field supports macro expansion. ``testLoad`` - - An optional integer. Equivalent to passing ``--test-load`` on the - command line. + An optional integer. Equivalent to passing + :option:`--test-load <ctest --test-load>` on the command line. ``showOnly`` - - An optional string. Equivalent to passing ``--show-only`` on the + An optional string. Equivalent to passing + :option:`--show-only <ctest --show-only>` on the command line. The string must be one of the following values: ``human`` @@ -876,13 +812,11 @@ that may contain the following fields: ``json-v1`` ``repeat`` - An optional object specifying how to repeat tests. Equivalent to - passing ``--repeat`` on the command line. The object must have the - following fields. + passing :option:`--repeat <ctest --repeat>` on the command line. + The object must have the following fields. ``mode`` - A required string. Must be one of the following values: ``until-fail`` @@ -892,42 +826,204 @@ that may contain the following fields: ``after-timeout`` ``count`` - A required integer. ``interactiveDebugging`` - An optional bool. If true, equivalent to passing - ``--interactive-debug-mode 1`` on the command line. If false, - equivalent to passing ``--interactive-debug-mode 0`` on the command - line. + :option:`--interactive-debug-mode 1 <ctest --interactive-debug-mode>` + on the command line. If false, equivalent to passing + :option:`--interactive-debug-mode 0 <ctest --interactive-debug-mode>` + on the command line. ``scheduleRandom`` - - An optional bool. If true, equivalent to passing ``--schedule-random`` - on the command line. + An optional bool. If true, equivalent to passing + :option:`--schedule-random <ctest --schedule-random>` on the command + line. ``timeout`` - - An optional integer. Equivalent to passing ``--timeout`` on the - command line. + An optional integer. Equivalent to passing + :option:`--timeout <ctest --timeout>` on the command line. ``noTestsAction`` - An optional string specifying the behavior if no tests are found. Must be one of the following values: ``default`` - Equivalent to not passing any value on the command line. ``error`` - - Equivalent to passing ``--no-tests=error`` on the command line. + Equivalent to passing :option:`--no-tests=error <ctest --no-tests>` + on the command line. ``ignore`` + Equivalent to passing :option:`--no-tests=ignore <ctest --no-tests>` + on the command line. + +Package Preset +^^^^^^^^^^^^^^ + +Package presets may be used in schema version ``6`` or above. Each entry of +the ``packagePresets`` array is a JSON object that may contain the following +fields: + +``name`` + A required string representing the machine-friendly name of the preset. + This identifier is used in the :option:`cpack --preset` option. + There must not be two package presets in the union of ``CMakePresets.json`` + and ``CMakeUserPresets.json`` in the same directory with the same name. + However, a package preset may have the same name as a configure, build, + test, or workflow preset. + +``hidden`` + An optional boolean specifying whether or not a preset should be hidden. + If a preset is hidden, it cannot be used in the + :option:`--preset <cpack --preset>` argument + and does not have to have a valid ``configurePreset``, even from + inheritance. ``hidden`` presets are intended to be used as a base for + other presets to inherit via the ``inherits`` field. + +``inherits`` + An optional array of strings representing the names of presets to inherit + from. This field can also be a string, which is equivalent to an array + containing one string. + + The preset will inherit all of the fields from the + ``inherits`` presets by default (except ``name``, ``hidden``, + ``inherits``, ``description``, and ``displayName``), but can override + them as desired. If multiple ``inherits`` presets provide conflicting + values for the same field, the earlier preset in the ``inherits`` list + will be preferred. + + A preset can only inherit from another preset that is defined in the + same file or in one of the files it includes (directly or indirectly). + Presets in ``CMakePresets.json`` may not inherit from presets in + ``CMakeUserPresets.json``. + +``condition`` + An optional `Condition`_ object. + +``vendor`` + An optional map containing vendor-specific information. CMake does not + interpret the contents of this field except to verify that it is a map + if it does exist. However, it should follow the same conventions as the + root-level ``vendor`` field. If vendors use their own per-preset + ``vendor`` field, they should implement inheritance in a sensible manner + when appropriate. + +``displayName`` + An optional string with a human-friendly name of the preset. - Equivalent to passing ``--no-tests=ignore`` on the command line. +``description`` + An optional string with a human-friendly description of the preset. + +``environment`` + An optional map of environment variables. The key is the variable name + (which may not be an empty string), and the value is either ``null`` or + a string representing the value of the variable. Each variable is set + regardless of whether or not a value was given to it by the process's + environment. This field supports macro expansion, and environment + variables in this map may reference each other, and may be listed in any + order, as long as such references do not cause a cycle (for example, if + ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2`` may not be ``$env{ENV_1}``.) + + Environment variables are inherited through the ``inherits`` field, and + the preset's environment will be the union of its own ``environment`` + and the ``environment`` from all its parents. If multiple presets in + this union define the same variable, the standard rules of ``inherits`` + are applied. Setting a variable to ``null`` causes it to not be set, + even if a value was inherited from another preset. + +``configurePreset`` + An optional string specifying the name of a configure preset to + associate with this package preset. If ``configurePreset`` is not + specified, it must be inherited from the inherits preset (unless this + preset is hidden). The build directory is inferred from the configure + preset, so packaging will run in the same ``binaryDir`` that the + configuration did and build did. + +``inheritConfigureEnvironment`` + An optional boolean that defaults to true. If true, the environment + variables from the associated configure preset are inherited after all + inherited package preset environments, but before environment variables + explicitly specified in this package preset. + +``generators`` + An optional list of strings representing generators for CPack to use. + +``configurations`` + An optional list of strings representing build configurations for CPack to + package. + +``variables`` + An optional map of variables to pass to CPack, equivalent to + :option:`-D <cpack -D>` arguments. Each key is the name of a variable, and + the value is the string to assign to that variable. + +``configFile`` + An optional string representing the config file for CPack to use. + +``output`` + An optional object specifying output options. Valid keys are: + + ``debug`` + An optional boolean specifying whether or not to print debug information. + A value of ``true`` is equivalent to passing + :option:`--debug <cpack --debug>` on the command line. + + ``verbose`` + An optional boolean specifying whether or not to print verbosely. A value + of ``true`` is equivalent to passing :option:`--verbose <cpack --verbose>` + on the command line. + +``packageName`` + An optional string representing the package name. + +``packageVersion`` + An optional string representing the package version. + +``packageDirectory`` + An optional string representing the directory in which to place the package. + +``vendorName`` + An optional string representing the vendor name. + +.. _`Workflow Preset`: + +Workflow Preset +^^^^^^^^^^^^^^^ + +Workflow presets may be used in schema version ``6`` or above. Each entry of +the ``workflowPresets`` array is a JSON object that may contain the following +fields: + +``name`` + A required string representing the machine-friendly name of the preset. + This identifier is used in the + :ref:`cmake --workflow --preset <Workflow Mode>` option. There must not be + two workflow presets in the union of ``CMakePresets.json`` and + ``CMakeUserPresets.json`` in the same directory with the same name. However, + a workflow preset may have the same name as a configure, build, test, or + package preset. + +``displayName`` + An optional string with a human-friendly name of the preset. + +``description`` + An optional string with a human-friendly description of the preset. + +``steps`` + A required array of objects describing the steps of the workflow. The first + step must be a configure preset, and all subsequent steps must be non- + configure presets whose ``configurePreset`` field matches the starting + configure preset. Each object may contain the following fields: + + ``type`` + A required string. The first step must be ``configure``. Subsequent steps + must be either ``build``, ``test``, or ``package``. + + ``name`` + A required string representing the name of the configure, build, test, or + package preset to run as this workflow step. Condition ^^^^^^^^^ @@ -943,65 +1039,53 @@ a ``not``, ``anyOf``, or ``allOf`` condition) may not be ``null``. If it is an object, it has the following fields: ``type`` - A required string with one of the following values: ``"const"`` - Indicates that the condition is constant. This is equivalent to using a boolean in place of the object. The condition object will have the following additional fields: ``value`` - A required boolean which provides a constant value for the condition's evaluation. ``"equals"`` ``"notEquals"`` - Indicates that the condition compares two strings to see if they are equal (or not equal). The condition object will have the following additional fields: ``lhs`` - First string to compare. This field supports macro expansion. ``rhs`` - Second string to compare. This field supports macro expansion. ``"inList"`` ``"notInList"`` - Indicates that the condition searches for a string in a list of strings. The condition object will have the following additional fields: ``string`` - A required string to search for. This field supports macro expansion. ``list`` - A required list of strings to search. This field supports macro expansion, and uses short-circuit evaluation. ``"matches"`` ``"notMatches"`` - Indicates that the condition searches for a regular expression in a string. The condition object will have the following additional fields: ``string`` - A required string to search. This field supports macro expansion. ``regex`` - A required regular expression to search for. This field supports macro expansion. @@ -1013,17 +1097,14 @@ object, it has the following fields: conditions. The condition object will have the following additional fields: ``conditions`` - A required array of condition objects. These conditions use short-circuit evaluation. ``"not"`` - Indicates that the condition is an inversion of another condition. The condition object will have the following additional fields: ``condition`` - A required condition object. Macro Expansion @@ -1045,46 +1126,37 @@ interpreted as a literal dollar sign. Recognized macros include: ``${sourceDir}`` - Path to the project source directory (i.e. the same as :variable:`CMAKE_SOURCE_DIR`). ``${sourceParentDir}`` - Path to the project source directory's parent directory. ``${sourceDirName}`` - The last filename component of ``${sourceDir}``. For example, if ``${sourceDir}`` is ``/path/to/source``, this would be ``source``. ``${presetName}`` - Name specified in the preset's ``name`` field. ``${generator}`` - Generator specified in the preset's ``generator`` field. For build and test presets, this will evaluate to the generator specified by ``configurePreset``. ``${hostSystemName}`` - The name of the host operating system. Contains the same value as :variable:`CMAKE_HOST_SYSTEM_NAME`. This is allowed in preset files specifying version ``3`` or above. ``${fileDir}`` - Path to the directory containing the preset file which contains the macro. This is allowed in preset files specifying version ``4`` or above. ``${dollar}`` - A literal dollar sign (``$``). ``${pathListSep}`` - Native character for separating lists of paths, such as ``:`` or ``;``. For example, by setting ``PATH`` to @@ -1095,7 +1167,6 @@ Recognized macros include: This is allowed in preset files specifying version ``5`` or above. ``$env{<variable-name>}`` - Environment variable with name ``<variable-name>``. The variable name may not be an empty string. If the variable is defined in the ``environment`` field, that value is used instead of the value from the parent environment. @@ -1108,7 +1179,6 @@ Recognized macros include: the casing of environment variable names consistent. ``$penv{<variable-name>}`` - Similar to ``$env{<variable-name>}``, except that the value only comes from the parent environment, and never from the ``environment`` field. This allows you to prepend or append values to existing environment variables. @@ -1118,7 +1188,6 @@ Recognized macros include: references. ``$vendor{<macro-name>}`` - An extension point for vendors to insert their own macros. CMake will not be able to use presets which have a ``$vendor{<macro-name>}`` macro, and effectively ignores such presets. However, it will still be able to use diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index d88322c..b17be82 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -90,6 +90,7 @@ Properties on Directories /prop_dir/RULE_LAUNCH_LINK /prop_dir/SOURCE_DIR /prop_dir/SUBDIRECTORIES + /prop_dir/SYSTEM /prop_dir/TESTS /prop_dir/TEST_INCLUDE_FILES /prop_dir/VARIABLES @@ -184,6 +185,16 @@ Properties on Targets /prop_tgt/CUDA_STANDARD /prop_tgt/CUDA_STANDARD_REQUIRED /prop_tgt/CXX_EXTENSIONS + /prop_tgt/CXX_MODULE_DIRS + /prop_tgt/CXX_MODULE_DIRS_NAME + /prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS + /prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME + /prop_tgt/CXX_MODULE_HEADER_UNIT_SET + /prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME + /prop_tgt/CXX_MODULE_HEADER_UNIT_SETS + /prop_tgt/CXX_MODULE_SET + /prop_tgt/CXX_MODULE_SET_NAME + /prop_tgt/CXX_MODULE_SETS /prop_tgt/CXX_STANDARD /prop_tgt/CXX_STANDARD_REQUIRED /prop_tgt/DEBUG_POSTFIX @@ -202,6 +213,7 @@ Properties on Targets /prop_tgt/EXCLUDE_FROM_DEFAULT_BUILD_CONFIG /prop_tgt/EXPORT_COMPILE_COMMANDS /prop_tgt/EXPORT_NAME + /prop_tgt/EXPORT_NO_SYSTEM /prop_tgt/EXPORT_PROPERTIES /prop_tgt/FOLDER /prop_tgt/Fortran_BUILDING_INSTRINSIC_MODULES @@ -262,6 +274,8 @@ Properties on Targets /prop_tgt/INTERFACE_COMPILE_DEFINITIONS /prop_tgt/INTERFACE_COMPILE_FEATURES /prop_tgt/INTERFACE_COMPILE_OPTIONS + /prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS + /prop_tgt/INTERFACE_CXX_MODULE_SETS /prop_tgt/INTERFACE_HEADER_SETS /prop_tgt/INTERFACE_HEADER_SETS_TO_VERIFY /prop_tgt/INTERFACE_INCLUDE_DIRECTORIES @@ -327,6 +341,7 @@ Properties on Targets /prop_tgt/MACOSX_RPATH /prop_tgt/MANUALLY_ADDED_DEPENDENCIES /prop_tgt/MAP_IMPORTED_CONFIG_CONFIG + /prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT /prop_tgt/MSVC_RUNTIME_LIBRARY /prop_tgt/NAME /prop_tgt/NO_SONAME @@ -342,8 +357,8 @@ Properties on Targets /prop_tgt/OSX_ARCHITECTURES_CONFIG /prop_tgt/OUTPUT_NAME /prop_tgt/OUTPUT_NAME_CONFIG - /prop_tgt/PCH_WARN_INVALID /prop_tgt/PCH_INSTANTIATE_TEMPLATES + /prop_tgt/PCH_WARN_INVALID /prop_tgt/PDB_NAME /prop_tgt/PDB_NAME_CONFIG /prop_tgt/PDB_OUTPUT_DIRECTORY @@ -375,6 +390,7 @@ Properties on Targets /prop_tgt/Swift_LANGUAGE_VERSION /prop_tgt/Swift_MODULE_DIRECTORY /prop_tgt/Swift_MODULE_NAME + /prop_tgt/SYSTEM /prop_tgt/TYPE /prop_tgt/UNITY_BUILD /prop_tgt/UNITY_BUILD_BATCH_SIZE @@ -444,13 +460,17 @@ Properties on Targets /prop_tgt/XCODE_SCHEME_ARGUMENTS /prop_tgt/XCODE_SCHEME_DEBUG_AS_ROOT /prop_tgt/XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING - /prop_tgt/XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE /prop_tgt/XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER /prop_tgt/XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS /prop_tgt/XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE + /prop_tgt/XCODE_SCHEME_ENABLE_GPU_API_VALIDATION + /prop_tgt/XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE + /prop_tgt/XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION /prop_tgt/XCODE_SCHEME_ENVIRONMENT /prop_tgt/XCODE_SCHEME_EXECUTABLE /prop_tgt/XCODE_SCHEME_GUARD_MALLOC + /prop_tgt/XCODE_SCHEME_LAUNCH_CONFIGURATION + /prop_tgt/XCODE_SCHEME_LAUNCH_MODE /prop_tgt/XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP /prop_tgt/XCODE_SCHEME_MALLOC_GUARD_EDGES /prop_tgt/XCODE_SCHEME_MALLOC_SCRIBBLE diff --git a/Help/manual/cmake-toolchains.7.rst b/Help/manual/cmake-toolchains.7.rst index e194df0..8a83807 100644 --- a/Help/manual/cmake-toolchains.7.rst +++ b/Help/manual/cmake-toolchains.7.rst @@ -17,6 +17,9 @@ determines the toolchain for host builds based on system introspection and defaults. In cross-compiling scenarios, a toolchain file may be specified with information about compiler and utility paths. +.. versionadded:: 3.19 + One may use :manual:`cmake-presets(7)` to specify toolchain files. + Languages ========= @@ -58,20 +61,24 @@ Variables and Properties ======================== Several variables relate to the language components of a toolchain which are -enabled. :variable:`CMAKE_<LANG>_COMPILER` is the full path to the compiler used -for ``<LANG>``. :variable:`CMAKE_<LANG>_COMPILER_ID` is the identifier used -by CMake for the compiler and :variable:`CMAKE_<LANG>_COMPILER_VERSION` is the -version of the compiler. - -The :variable:`CMAKE_<LANG>_FLAGS` variables and the configuration-specific -equivalents contain flags that will be added to the compile command when -compiling a file of a particular language. - -As the linker is invoked by the compiler driver, CMake needs a way to determine -which compiler to use to invoke the linker. This is calculated by the -:prop_sf:`LANGUAGE` of source files in the target, and in the case of static -libraries, the language of the dependent libraries. The choice CMake makes may -be overridden with the :prop_tgt:`LINKER_LANGUAGE` target property. +enabled: + +:variable:`CMAKE_<LANG>_COMPILER` + The full path to the compiler used for ``<LANG>`` +:variable:`CMAKE_<LANG>_COMPILER_ID` + The compiler identifier used by CMake +:variable:`CMAKE_<LANG>_COMPILER_VERSION` + The version of the compiler. +:variable:`CMAKE_<LANG>_FLAGS` + The variables and the configuration-specific equivalents contain flags that + will be added to the compile command when compiling a file of a particular + language. + +CMake needs a way to determine which compiler to use to invoke the linker. +This is determined by the :prop_sf:`LANGUAGE` property of source files of the +:manual:`target <cmake-buildsystem(7)>`, and in the case of static libraries, +the ``LANGUAGE`` of the dependent libraries. The choice CMake makes may be overridden +with the :prop_tgt:`LINKER_LANGUAGE` target property. Toolchain Features ================== @@ -96,7 +103,8 @@ Cross Compiling =============== If :manual:`cmake(1)` is invoked with the command line parameter -``--toolchain path/to/file`` or ``-DCMAKE_TOOLCHAIN_FILE=path/to/file``, the +:option:`--toolchain path/to/file <cmake --toolchain>` or +:option:`-DCMAKE_TOOLCHAIN_FILE=path/to/file <cmake -D>`, the file will be loaded early to set values for the compilers. The :variable:`CMAKE_CROSSCOMPILING` variable is set to true when CMake is cross-compiling. @@ -132,24 +140,24 @@ as: set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -The :variable:`CMAKE_SYSTEM_NAME` is the CMake-identifier of the target platform -to build for. - -The :variable:`CMAKE_SYSTEM_PROCESSOR` is the CMake-identifier of the target architecture -to build for. +Where: -The :variable:`CMAKE_SYSROOT` is optional, and may be specified if a sysroot -is available. - -The :variable:`CMAKE_STAGING_PREFIX` is also optional. It may be used to specify -a path on the host to install to. The :variable:`CMAKE_INSTALL_PREFIX` is always -the runtime installation location, even when cross-compiling. - -The :variable:`CMAKE_<LANG>_COMPILER` variables may be set to full paths, or to -names of compilers to search for in standard locations. For toolchains that -do not support linking binaries without custom flags or scripts one may set -the :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable to ``STATIC_LIBRARY`` -to tell CMake not to try to link executables during its checks. +:variable:`CMAKE_SYSTEM_NAME` + is the CMake-identifier of the target platform to build for. +:variable:`CMAKE_SYSTEM_PROCESSOR` + is the CMake-identifier of the target architecture. +:variable:`CMAKE_SYSROOT` + is optional, and may be specified if a sysroot is available. +:variable:`CMAKE_STAGING_PREFIX` + is also optional. It may be used to specify a path on the host to install to. + The :variable:`CMAKE_INSTALL_PREFIX` is always the runtime installation + location, even when cross-compiling. +:variable:`CMAKE_<LANG>_COMPILER` + variable may be set to full paths, or to names of compilers to search for + in standard locations. For toolchains that do not support linking binaries + without custom flags or scripts one may set the + :variable:`CMAKE_TRY_COMPILE_TARGET_TYPE` variable to ``STATIC_LIBRARY`` to + tell CMake not to try to link executables during its checks. CMake ``find_*`` commands will look in the sysroot, and the :variable:`CMAKE_FIND_ROOT_PATH` entries by default in all cases, as well as looking in the host system root prefix. diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index 7c8a7fa..cd46615 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -128,9 +128,9 @@ Variables that Provide Information /variable/CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR /variable/CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE /variable/CMAKE_VS_PLATFORM_TOOLSET_VERSION - /variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION /variable/CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER /variable/CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION + /variable/CMAKE_VS_TARGET_FRAMEWORK_VERSION /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION /variable/CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM /variable/CMAKE_XCODE_BUILD_SYSTEM @@ -207,9 +207,9 @@ Variables that Change Behavior /variable/CMAKE_FIND_ROOT_PATH_MODE_PACKAGE /variable/CMAKE_FIND_ROOT_PATH_MODE_PROGRAM /variable/CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH - /variable/CMAKE_FIND_USE_INSTALL_PREFIX /variable/CMAKE_FIND_USE_CMAKE_PATH /variable/CMAKE_FIND_USE_CMAKE_SYSTEM_PATH + /variable/CMAKE_FIND_USE_INSTALL_PREFIX /variable/CMAKE_FIND_USE_PACKAGE_REGISTRY /variable/CMAKE_FIND_USE_PACKAGE_ROOT_PATH /variable/CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH @@ -228,12 +228,12 @@ Variables that Change Behavior /variable/CMAKE_LIBRARY_PATH /variable/CMAKE_LINK_DIRECTORIES_BEFORE /variable/CMAKE_LINK_LIBRARIES_ONLY_TARGETS - /variable/CMAKE_MFC_FLAG /variable/CMAKE_MAXIMUM_RECURSION_DEPTH /variable/CMAKE_MESSAGE_CONTEXT /variable/CMAKE_MESSAGE_CONTEXT_SHOW /variable/CMAKE_MESSAGE_INDENT /variable/CMAKE_MESSAGE_LOG_LEVEL + /variable/CMAKE_MFC_FLAG /variable/CMAKE_MODULE_PATH /variable/CMAKE_POLICY_DEFAULT_CMPNNNN /variable/CMAKE_POLICY_WARNING_CMPNNNN @@ -272,12 +272,16 @@ Variables that Change Behavior /variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER /variable/CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN /variable/CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING - /variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE /variable/CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS /variable/CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE + /variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION + /variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE + /variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION /variable/CMAKE_XCODE_SCHEME_ENVIRONMENT /variable/CMAKE_XCODE_SCHEME_GUARD_MALLOC + /variable/CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION + /variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE /variable/CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP /variable/CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES /variable/CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE @@ -300,10 +304,13 @@ Variables that Describe the System /variable/ANDROID /variable/APPLE /variable/BORLAND + /variable/BSD /variable/CMAKE_ANDROID_NDK_VERSION /variable/CMAKE_CL_64 /variable/CMAKE_COMPILER_2005 /variable/CMAKE_HOST_APPLE + /variable/CMAKE_HOST_BSD + /variable/CMAKE_HOST_LINUX /variable/CMAKE_HOST_SOLARIS /variable/CMAKE_HOST_SYSTEM /variable/CMAKE_HOST_SYSTEM_NAME @@ -321,6 +328,7 @@ Variables that Describe the System /variable/CYGWIN /variable/GHSMULTI /variable/IOS + /variable/LINUX /variable/MINGW /variable/MSVC /variable/MSVC10 @@ -412,19 +420,19 @@ Variables that Control the Build /variable/CMAKE_DEBUG_POSTFIX /variable/CMAKE_DEFAULT_BUILD_TYPE /variable/CMAKE_DEFAULT_CONFIGS - /variable/CMAKE_DISABLE_PRECOMPILE_HEADERS /variable/CMAKE_DEPENDS_USE_COMPILER + /variable/CMAKE_DISABLE_PRECOMPILE_HEADERS /variable/CMAKE_ENABLE_EXPORTS /variable/CMAKE_EXE_LINKER_FLAGS /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG /variable/CMAKE_EXE_LINKER_FLAGS_CONFIG_INIT /variable/CMAKE_EXE_LINKER_FLAGS_INIT /variable/CMAKE_FOLDER - /variable/CMAKE_FRAMEWORK - /variable/CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG /variable/CMAKE_Fortran_FORMAT /variable/CMAKE_Fortran_MODULE_DIRECTORY /variable/CMAKE_Fortran_PREPROCESS + /variable/CMAKE_FRAMEWORK + /variable/CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_CONFIG /variable/CMAKE_GHS_NO_SOURCE_GROUP_FILE /variable/CMAKE_GLOBAL_AUTOGEN_TARGET /variable/CMAKE_GLOBAL_AUTOGEN_TARGET_NAME @@ -445,14 +453,14 @@ Variables that Control the Build /variable/CMAKE_LANG_CPPCHECK /variable/CMAKE_LANG_CPPLINT /variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE - /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE - /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE_SUPPORTED - /variable/CMAKE_LANG_LINKER_LAUNCHER /variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE /variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED /variable/CMAKE_LANG_LINK_LIBRARY_FILE_FLAG /variable/CMAKE_LANG_LINK_LIBRARY_FLAG + /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE + /variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE_SUPPORTED /variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG + /variable/CMAKE_LANG_LINKER_LAUNCHER /variable/CMAKE_LANG_VISIBILITY_PRESET /variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY /variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY_CONFIG @@ -475,8 +483,9 @@ Variables that Control the Build /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG /variable/CMAKE_MODULE_LINKER_FLAGS_CONFIG_INIT /variable/CMAKE_MODULE_LINKER_FLAGS_INIT - /variable/CMAKE_MSVCIDE_RUN_PATH + /variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT /variable/CMAKE_MSVC_RUNTIME_LIBRARY + /variable/CMAKE_MSVCIDE_RUN_PATH /variable/CMAKE_NINJA_OUTPUT_PATH_PREFIX /variable/CMAKE_NO_BUILTIN_CHRPATH /variable/CMAKE_NO_SYSTEM_FROM_IMPORTED @@ -484,8 +493,8 @@ Variables that Control the Build /variable/CMAKE_OSX_ARCHITECTURES /variable/CMAKE_OSX_DEPLOYMENT_TARGET /variable/CMAKE_OSX_SYSROOT - /variable/CMAKE_PCH_WARN_INVALID /variable/CMAKE_PCH_INSTANTIATE_TEMPLATES + /variable/CMAKE_PCH_WARN_INVALID /variable/CMAKE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_PLATFORM_NO_VERSIONED_SONAME @@ -502,6 +511,7 @@ Variables that Control the Build /variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG /variable/CMAKE_STATIC_LINKER_FLAGS_CONFIG_INIT /variable/CMAKE_STATIC_LINKER_FLAGS_INIT + /variable/CMAKE_TASKING_TOOLSET /variable/CMAKE_TRY_COMPILE_CONFIGURATION /variable/CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES /variable/CMAKE_TRY_COMPILE_PLATFORM_VARIABLES @@ -538,6 +548,10 @@ Variables for Languages .. toctree:: :maxdepth: 1 + /variable/CMAKE_C_COMPILE_FEATURES + /variable/CMAKE_C_EXTENSIONS + /variable/CMAKE_C_STANDARD + /variable/CMAKE_C_STANDARD_REQUIRED /variable/CMAKE_COMPILER_IS_GNUCC /variable/CMAKE_COMPILER_IS_GNUCXX /variable/CMAKE_COMPILER_IS_GNUG77 @@ -552,10 +566,6 @@ Variables for Languages /variable/CMAKE_CXX_EXTENSIONS /variable/CMAKE_CXX_STANDARD /variable/CMAKE_CXX_STANDARD_REQUIRED - /variable/CMAKE_C_COMPILE_FEATURES - /variable/CMAKE_C_EXTENSIONS - /variable/CMAKE_C_STANDARD - /variable/CMAKE_C_STANDARD_REQUIRED /variable/CMAKE_Fortran_MODDIR_DEFAULT /variable/CMAKE_Fortran_MODDIR_FLAG /variable/CMAKE_Fortran_MODOUT_FLAG @@ -573,6 +583,7 @@ Variables for Languages /variable/CMAKE_LANG_ARCHIVE_CREATE /variable/CMAKE_LANG_ARCHIVE_FINISH /variable/CMAKE_LANG_BYTE_ORDER + /variable/CMAKE_LANG_COMPILE_OBJECT /variable/CMAKE_LANG_COMPILER /variable/CMAKE_LANG_COMPILER_EXTERNAL_TOOLCHAIN /variable/CMAKE_LANG_COMPILER_ID @@ -580,7 +591,6 @@ Variables for Languages /variable/CMAKE_LANG_COMPILER_PREDEFINES_COMMAND /variable/CMAKE_LANG_COMPILER_TARGET /variable/CMAKE_LANG_COMPILER_VERSION - /variable/CMAKE_LANG_COMPILE_OBJECT /variable/CMAKE_LANG_CREATE_SHARED_LIBRARY /variable/CMAKE_LANG_CREATE_SHARED_MODULE /variable/CMAKE_LANG_CREATE_STATIC_LIBRARY @@ -653,12 +663,12 @@ Variables for CTest /variable/CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS /variable/CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS /variable/CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE - /variable/CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION /variable/CTEST_CUSTOM_MEMCHECK_IGNORE /variable/CTEST_CUSTOM_POST_MEMCHECK /variable/CTEST_CUSTOM_POST_TEST /variable/CTEST_CUSTOM_PRE_MEMCHECK /variable/CTEST_CUSTOM_PRE_TEST + /variable/CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION /variable/CTEST_CUSTOM_TESTS_IGNORE /variable/CTEST_CUSTOM_WARNING_EXCEPTION /variable/CTEST_CUSTOM_WARNING_MATCH @@ -694,9 +704,9 @@ Variables for CTest /variable/CTEST_SCP_COMMAND /variable/CTEST_SCRIPT_DIRECTORY /variable/CTEST_SITE + /variable/CTEST_SOURCE_DIRECTORY /variable/CTEST_SUBMIT_INACTIVITY_TIMEOUT /variable/CTEST_SUBMIT_URL - /variable/CTEST_SOURCE_DIRECTORY /variable/CTEST_SVN_COMMAND /variable/CTEST_SVN_OPTIONS /variable/CTEST_SVN_UPDATE_OPTIONS diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 38105dd..35bd05f 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -9,8 +9,7 @@ Synopsis .. parsed-literal:: `Generate a Project Buildsystem`_ - cmake [<options>] <path-to-source> - cmake [<options>] <path-to-existing-build> + cmake [<options>] <path-to-source | path-to-existing-build> cmake [<options>] -S <path-to-source> -B <path-to-build> `Build a Project`_ @@ -23,7 +22,7 @@ Synopsis cmake --open <dir> `Run a Script`_ - cmake [{-D <var>=<value>}...] -P <cmake-script-file> + cmake [-D <var>=<value>]... -P <cmake-script-file> `Run a Command-Line Tool`_ cmake -E <command> [<options>] @@ -31,6 +30,9 @@ Synopsis `Run the Find-Package Tool`_ cmake --find-package [<options>] + `Run a Workflow Preset`_ + cmake --workflow [<options>] + `View Help`_ cmake --help[-<topic>] @@ -96,9 +98,10 @@ Build Tree Generator This chooses the kind of buildsystem to generate. See the :manual:`cmake-generators(7)` manual for documentation of all generators. - Run ``cmake --help`` to see a list of generators available locally. - Optionally use the ``-G`` option below to specify a generator, or simply - accept the default CMake chooses for the current platform. + Run :option:`cmake --help` to see a list of generators available locally. + Optionally use the :option:`-G <cmake -G>` option below to specify a + generator, or simply accept the default CMake chooses for the current + platform. When using one of the :ref:`Command-Line Build Tool Generators` CMake expects that the environment needed by the compiler toolchain @@ -139,6 +142,9 @@ source and build trees and generate a buildsystem: $ cmake . ``cmake [<options>] -S <path-to-source> -B <path-to-build>`` + + .. versionadded:: 3.13 + Uses ``<path-to-build>`` as the build tree and ``<path-to-source>`` as the source tree. The specified paths may be absolute or relative to the current working directory. The source tree must contain a @@ -152,11 +158,11 @@ source and build trees and generate a buildsystem: In all cases the ``<options>`` may be zero or more of the `Options`_ below. The above styles for specifying the source and build trees may be mixed. -Paths specified with ``-S`` or ``-B`` are always classified as source or -build trees, respectively. Paths specified with plain arguments are -classified based on their content and the types of paths given earlier. -If only one type of path is given, the current working directory (cwd) -is used for the other. For example: +Paths specified with :option:`-S <cmake -S>` or :option:`-B <cmake -B>` +are always classified as source or build trees, respectively. Paths +specified with plain arguments are classified based on their content +and the types of paths given earlier. If only one type of path is given, +the current working directory (cwd) is used for the other. For example: ============================== ============ =========== Command Line Source Dir Build Dir @@ -195,51 +201,60 @@ automatically choosing and invoking the appropriate native build tool. Options ------- +.. program:: cmake + .. include:: OPTIONS_BUILD.txt -``--fresh`` +.. option:: --fresh + .. versionadded:: 3.24 Perform a fresh configuration of the build tree. This removes any existing ``CMakeCache.txt`` file and associated ``CMakeFiles/`` directory, and recreates them from scratch. -``-L[A][H]`` +.. option:: -L[A][H] + List non-advanced cached variables. List ``CACHE`` variables will run CMake and list all the variables from the CMake ``CACHE`` that are not marked as ``INTERNAL`` or :prop_cache:`ADVANCED`. This will effectively display current CMake settings, which can then be - changed with ``-D`` option. Changing some of the variables may result - in more variables being created. If ``A`` is specified, then it will - display also advanced variables. If ``H`` is specified, it will also + changed with :option:`-D <cmake -D>` option. Changing some of the variables + may result in more variables being created. If ``A`` is specified, then it + will display also advanced variables. If ``H`` is specified, it will also display help for each variable. -``-N`` +.. option:: -N + View mode only. Only load the cache. Do not actually run configure and generate steps. -``--graphviz=[file]`` +.. option:: --graphviz=<file> + Generate graphviz of dependencies, see :module:`CMakeGraphVizOptions` for more. Generate a graphviz input file that will contain all the library and executable dependencies in the project. See the documentation for :module:`CMakeGraphVizOptions` for more details. -``--system-information [file]`` +.. option:: --system-information [file] + Dump information about this system. Dump a wide range of information about the current system. If run from the top of a binary tree for a CMake project it will dump additional information such as the cache, log files etc. -``--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>`` - Set the log level. +.. option:: --log-level=<level> + + Set the log ``<level>``. The :command:`message` command will only output messages of the specified - log level or higher. The default log level is ``STATUS``. + log level or higher. The valid log levels are ``ERROR``, ``WARNING``, + ``NOTICE``, ``STATUS`` (default), ``VERBOSE``, ``DEBUG``, or ``TRACE``. To make a log level persist between CMake runs, set :variable:`CMAKE_MESSAGE_LOG_LEVEL` as a cache variable instead. @@ -249,7 +264,12 @@ Options For backward compatibility reasons, ``--loglevel`` is also accepted as a synonym for this option. -``--log-context`` + .. versionadded:: 3.25 + See the :command:`cmake_language` command for a way to + :ref:`query the current message logging level <query_message_log_level>`. + +.. option:: --log-context + Enable the :command:`message` command outputting context attached to each message. @@ -259,24 +279,36 @@ Options When this command line option is given, :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` is ignored. -``--debug-trycompile`` - Do not delete the :command:`try_compile` build tree. - Only useful on one :command:`try_compile` at a time. +.. option:: --debug-trycompile + + Do not delete the files and directories created for + :command:`try_compile` / :command:`try_run` calls. + This is useful in debugging failed checks. + + Note that some uses of :command:`try_compile` may use the same build tree, + which will limit the usefulness of this option if a project executes more + than one :command:`try_compile`. For example, such uses may change results + as artifacts from a previous try-compile may cause a different test to either + pass or fail incorrectly. This option is best used only when debugging. + + (With respect to the preceding, the :command:`try_run` command + is effectively a :command:`try_compile`. Any combination of the two + is subject to the potential issues described.) - Do not delete the files and directories created for :command:`try_compile` - calls. This is useful in debugging failed try_compiles. It may - however change the results of the try-compiles as old junk from a - previous try-compile may cause a different test to either pass or - fail incorrectly. This option is best used for one try-compile at a - time, and only when debugging. + .. versionadded:: 3.25 + + When this option is enabled, every try-compile check prints a log + message reporting the directory in which the check is performed. + +.. option:: --debug-output -``--debug-output`` Put cmake in a debug mode. Print extra information during the cmake run like stack traces with :command:`message(SEND_ERROR)` calls. -``--debug-find`` +.. option:: --debug-find + Put cmake find commands in a debug mode. Print extra find call information during the cmake run to standard @@ -284,32 +316,39 @@ Options See also the :variable:`CMAKE_FIND_DEBUG_MODE` variable for debugging a more local part of the project. -``--debug-find-pkg=<pkg>[,...]`` +.. option:: --debug-find-pkg=<pkg>[,...] + Put cmake find commands in a debug mode when running under calls to :command:`find_package(\<pkg\>) <find_package>`, where ``<pkg>`` is an entry in the given comma-separated list of case-sensitive package names. - Like ``--debug-find``, but limiting scope to the specified packages. + Like :option:`--debug-find <cmake --debug-find>`, but limiting scope + to the specified packages. + +.. option:: --debug-find-var=<var>[,...] -``--debug-find-var=<var>[,...]`` Put cmake find commands in a debug mode when called with ``<var>`` as the result variable, where ``<var>`` is an entry in the given comma-separated list. - Like ``--debug-find``, but limiting scope to the specified variable names. + Like :option:`--debug-find <cmake --debug-find>`, but limiting scope + to the specified variable names. + +.. option:: --trace -``--trace`` Put cmake in trace mode. Print a trace of all calls made and from where. -``--trace-expand`` +.. option:: --trace-expand + Put cmake in trace mode. - Like ``--trace``, but with variables expanded. + Like :option:`--trace <cmake --trace>`, but with variables expanded. + +.. option:: --trace-format=<format> -``--trace-format=<format>`` Put cmake in trace mode and sets the trace output format. ``<format>`` can be one of the following values. @@ -395,46 +434,57 @@ Options Indicates the version of the JSON format. The version has a major and minor components following semantic version conventions. -``--trace-source=<file>`` +.. option:: --trace-source=<file> + Put cmake in trace mode, but output only lines of a specified file. Multiple options are allowed. -``--trace-redirect=<file>`` +.. option:: --trace-redirect=<file> + Put cmake in trace mode and redirect trace output to a file instead of stderr. -``--warn-uninitialized`` +.. option:: --warn-uninitialized + Warn about uninitialized values. Print a warning when an uninitialized variable is used. -``--warn-unused-vars`` +.. option:: --warn-unused-vars + Does nothing. In CMake versions 3.2 and below this enabled warnings about unused variables. In CMake versions 3.3 through 3.18 the option was broken. In CMake 3.19 and above the option has been removed. -``--no-warn-unused-cli`` +.. option:: --no-warn-unused-cli + Don't warn about command line options. Don't find variables that are declared on the command line, but not used. -``--check-system-vars`` +.. option:: --check-system-vars + Find problems with variable usage in system files. Normally, unused and uninitialized variables are searched for only in :variable:`CMAKE_SOURCE_DIR` and :variable:`CMAKE_BINARY_DIR`. This flag tells CMake to warn about other files as well. -``--compile-no-warning-as-error`` +.. option:: --compile-no-warning-as-error + Ignore target property :prop_tgt:`COMPILE_WARNING_AS_ERROR` and variable :variable:`CMAKE_COMPILE_WARNING_AS_ERROR`, preventing warnings from being treated as errors on compile. -``--profiling-output=<path>`` - Used in conjunction with ``--profiling-format`` to output to a given path. +.. option:: --profiling-output=<path> + + Used in conjunction with + :option:`--profiling-format <cmake --profiling-format>` to output to a + given path. + +.. option:: --profiling-format=<file> -``--profiling-format=<file>`` Enable the output of profiling data of CMake script in the given format. This can aid performance analysis of CMake scripts executed. Third party @@ -445,7 +495,8 @@ Options about:tracing tab of Google Chrome or using a plugin for a tool like Trace Compass. -``--preset <preset>``, ``--preset=<preset>`` +.. option:: --preset <preset>, --preset=<preset> + Reads a :manual:`preset <cmake-presets(7)>` from ``<path-to-source>/CMakePresets.json`` and ``<path-to-source>/CMakeUserPresets.json``. The preset may specify the @@ -461,15 +512,20 @@ Options a variable called ``MYVAR`` to ``1``, but the user sets it to ``2`` with a ``-D`` argument, the value ``2`` is preferred. -``--list-presets, --list-presets=<[configure | build | test | all]>`` - Lists the available presets. If no option is specified only configure presets - will be listed. The current working directory must contain CMake preset files. +.. option:: --list-presets[=<type>] + + Lists the available presets of the specified ``<type>``. Valid values for + ``<type>`` are ``configure``, ``build``, ``test``, ``package``, or ``all``. + If ``<type>`` is omitted, ``configure`` is assumed. The current working + directory must contain CMake preset files. .. _`Build Tool Mode`: Build a Project =============== +.. program:: cmake + CMake provides a command-line signature to build an already-generated project binary tree: @@ -481,21 +537,29 @@ project binary tree: This abstracts a native build tool's command-line interface with the following options: -``--build <dir>`` +.. option:: --build <dir> + Project binary directory to be built. This is required (unless a preset is specified) and must be first. -``--preset <preset>``, ``--preset=<preset>`` +.. program:: cmake--build + +.. option:: --preset <preset>, --preset=<preset> + Use a build preset to specify build options. The project binary directory is inferred from the ``configurePreset`` key. The current working directory must contain CMake preset files. See :manual:`preset <cmake-presets(7)>` for more details. -``--list-presets`` +.. option:: --list-presets + Lists the available build presets. The current working directory must contain CMake preset files. -``--parallel [<jobs>], -j [<jobs>]`` +.. option:: -j [<jobs>], --parallel [<jobs>] + + .. versionadded:: 3.12 + The maximum number of concurrent processes to use when building. If ``<jobs>`` is omitted the native build tool's default number is used. @@ -505,24 +569,29 @@ following options: Some native build tools always build in parallel. The use of ``<jobs>`` value of ``1`` can be used to limit to a single job. -``--target <tgt>..., -t <tgt>...`` +.. option:: -t <tgt>..., --target <tgt>... + Build ``<tgt>`` instead of the default target. Multiple targets may be given, separated by spaces. -``--config <cfg>`` +.. option:: --config <cfg> + For multi-configuration tools, choose configuration ``<cfg>``. -``--clean-first`` +.. option:: --clean-first + Build target ``clean`` first, then build. - (To clean only, use ``--target clean``.) + (To clean only, use :option:`--target clean <cmake--build --target>`.) + +.. option:: --resolve-package-references=<value> -``--resolve-package-references=<on|off|only>`` .. versionadded:: 3.23 Resolve remote package references from external package managers (e.g. NuGet) - before build. When set to ``on`` (default), packages will be restored before - building a target. When set to ``only``, the packages will be restored, but no - build will be performed. When set to ``off``, no packages will be restored. + before build. When ``<value>`` is set to ``on`` (default), packages will be + restored before building a target. When ``<value>`` is set to ``only``, the + packages will be restored, but no build will be performed. When + ``<value>`` is set to ``off``, no packages will be restored. If the target does not define any package references, this option does nothing. @@ -539,10 +608,12 @@ following options: are restored using NuGet. It can be disabled by setting the ``CMAKE_VS_NUGET_PACKAGE_RESTORE`` variable to ``OFF``. -``--use-stderr`` +.. option:: --use-stderr + Ignored. Behavior is default in CMake >= 3.0. -``--verbose, -v`` +.. option:: -v, --verbose + Enable verbose output - if supported - including the build commands to be executed. @@ -550,14 +621,17 @@ following options: :variable:`CMAKE_VERBOSE_MAKEFILE` cached variable is set. -``--`` +.. option:: -- + Pass remaining options to the native tool. -Run ``cmake --build`` with no options for quick help. +Run :option:`cmake --build` with no options for quick help. Install a Project ================= +.. program:: cmake + CMake provides a command-line signature to install an already-generated project binary tree: @@ -569,34 +643,45 @@ This may be used after building a project to run installation without using the generated build system or the native build tool. The options are: -``--install <dir>`` +.. option:: --install <dir> + Project binary directory to install. This is required and must be first. -``--config <cfg>`` +.. program:: cmake--install + +.. option:: --config <cfg> + For multi-configuration generators, choose configuration ``<cfg>``. -``--component <comp>`` +.. option:: --component <comp> + Component-based install. Only install component ``<comp>``. -``--default-directory-permissions <permissions>`` +.. option:: --default-directory-permissions <permissions> + Default directory install permissions. Permissions in format ``<u=rwx,g=rx,o=rx>``. -``--prefix <prefix>`` +.. option:: --prefix <prefix> + Override the installation prefix, :variable:`CMAKE_INSTALL_PREFIX`. -``--strip`` +.. option:: --strip + Strip before installing. -``-v, --verbose`` +.. option:: -v, --verbose + Enable verbose output. This option can be omitted if :envvar:`VERBOSE` environment variable is set. -Run ``cmake --install`` with no options for quick help. +Run :option:`cmake --install` with no options for quick help. Open a Project ============== +.. program:: cmake + .. code-block:: shell cmake --open <dir> @@ -610,14 +695,26 @@ supported by some generators. Run a Script ============ +.. program:: cmake + .. code-block:: shell - cmake [{-D <var>=<value>}...] -P <cmake-script-file> [-- <unparsed-options>...] + cmake [-D <var>=<value>]... -P <cmake-script-file> [-- <unparsed-options>...] + +.. program:: cmake-P + +.. option:: -D <var>=<value> -Process the given cmake file as a script written in the CMake -language. No configure or generate step is performed and the cache -is not modified. If variables are defined using ``-D``, this must be -done before the ``-P`` argument. + Define a variable for script mode. + +.. program:: cmake + +.. option:: -P <cmake-script-file> + + Process the given cmake file as a script written in the CMake + language. No configure or generate step is performed and the cache + is not modified. If variables are defined using ``-D``, this must be + done before the ``-P`` argument. Any options after ``--`` are not parsed by CMake, but they are still included in the set of :variable:`CMAKE_ARGV<n> <CMAKE_ARGV0>` variables passed to the @@ -629,16 +726,24 @@ script (including the ``--`` itself). Run a Command-Line Tool ======================= +.. program:: cmake + CMake provides builtin command-line tools through the signature .. code-block:: shell cmake -E <command> [<options>] -Run ``cmake -E`` or ``cmake -E help`` for a summary of commands. +.. option:: -E [help] + + Run ``cmake -E`` or ``cmake -E help`` for a summary of commands. + +.. program:: cmake-E + Available commands are: -``capabilities`` +.. option:: capabilities + .. versionadded:: 3.7 Report cmake capabilities in JSON format. The output is a JSON object @@ -648,7 +753,7 @@ Available commands are: A JSON object with version information. Keys are: ``string`` - The full version string as displayed by cmake ``--version``. + The full version string as displayed by cmake :option:`--version <cmake --version>`. ``major`` The major version number in integer form. ``minor`` @@ -675,7 +780,8 @@ Available commands are: Optional member that may be present when the generator supports platform specification via :variable:`CMAKE_GENERATOR_PLATFORM` - (``-A ...``). The value is a list of platforms known to be supported. + (:option:`-A ... <cmake -A>`). The value is a list of platforms known to + be supported. ``extraGenerators`` A list of strings with all the extra generators compatible with the generator. @@ -700,30 +806,52 @@ Available commands are: ``true`` if cmake supports server-mode and ``false`` otherwise. Always false since CMake 3.20. -``cat [--] <files>...`` + ``tls`` + .. versionadded:: 3.25 + + ``true`` if TLS support is enabled and ``false`` otherwise. + +.. option:: cat [--] <files>... + .. versionadded:: 3.18 Concatenate files and print on the standard output. - .. versionadded:: 3.24 + .. program:: cmake-E_cat + + .. option:: -- + + .. versionadded:: 3.24 + Added support for the double dash argument ``--``. This basic implementation of ``cat`` does not support any options, so using a option starting with ``-`` will result in an error. Use ``--`` to indicate the end of options, in case a file starts with ``-``. -``chdir <dir> <cmd> [<arg>...]`` +.. program:: cmake-E + +.. option:: chdir <dir> <cmd> [<arg>...] + Change the current working directory and run a command. -``compare_files [--ignore-eol] <file1> <file2>`` +.. option:: compare_files [--ignore-eol] <file1> <file2> + Check if ``<file1>`` is same as ``<file2>``. If files are the same, then returns ``0``, if not it returns ``1``. In case of invalid arguments, it returns 2. - .. versionadded:: 3.14 - The ``--ignore-eol`` option implies line-wise comparison and ignores - LF/CRLF differences. + .. program:: cmake-E_compare_files + + .. option:: --ignore-eol + + .. versionadded:: 3.14 + + The option implies line-wise comparison and ignores LF/CRLF differences. + +.. program:: cmake-E + +.. option:: copy <file>... <destination> -``copy <file>... <destination>`` Copy files to ``<destination>`` (either file or directory). If multiple files are specified, the ``<destination>`` must be directory and it must exist. Wildcards are not supported. @@ -733,7 +861,8 @@ Available commands are: .. versionadded:: 3.5 Support for multiple input files. -``copy_directory <dir>... <destination>`` +.. option:: copy_directory <dir>... <destination> + Copy content of ``<dir>...`` directories to ``<destination>`` directory. If ``<destination>`` directory does not exist it will be created. ``copy_directory`` does follow symlinks. @@ -745,7 +874,8 @@ Available commands are: The command now fails when the source directory does not exist. Previously it succeeded by creating an empty destination directory. -``copy_if_different <file>... <destination>`` +.. option:: copy_if_different <file>... <destination> + Copy files to ``<destination>`` (either file or directory) if they have changed. If multiple files are specified, the ``<destination>`` must be @@ -755,7 +885,8 @@ Available commands are: .. versionadded:: 3.5 Support for multiple input files. -``create_symlink <old> <new>`` +.. option:: create_symlink <old> <new> + Create a symbolic link ``<new>`` naming ``<old>``. .. versionadded:: 3.13 @@ -764,7 +895,8 @@ Available commands are: .. note:: Path to where ``<new>`` symbolic link will be created has to exist beforehand. -``create_hardlink <old> <new>`` +.. option:: create_hardlink <old> <new> + .. versionadded:: 3.19 Create a hard link ``<new>`` naming ``<old>``. @@ -773,31 +905,65 @@ Available commands are: Path to where ``<new>`` hard link will be created has to exist beforehand. ``<old>`` has to exist beforehand. -``echo [<string>...]`` +.. option:: echo [<string>...] + Displays arguments as text. -``echo_append [<string>...]`` +.. option:: echo_append [<string>...] + Displays arguments as text but no new line. -``env [--unset=NAME ...] [NAME=VALUE ...] [--] <command> [<arg>...]`` +.. option:: env [<options>] [--] <command> [<arg>...] + .. versionadded:: 3.1 - Run command in a modified environment. + Run command in a modified environment. Options are: + + .. program:: cmake-E_env + + .. option:: NAME=VALUE + + Replaces the current value of ``NAME`` with ``VALUE``. + + .. option:: --unset=NAME + + Unsets the current value of ``NAME``. + + .. option:: --modify ENVIRONMENT_MODIFICATION + + .. versionadded:: 3.25 + + Apply a single :prop_test:`ENVIRONMENT_MODIFICATION` operation to the + modified environment. + + The ``NAME=VALUE`` and ``--unset=NAME`` options are equivalent to + ``--modify NAME=set:VALUE`` and ``--modify NAME=unset:``, respectively. + Note that ``--modify NAME=reset:`` resets ``NAME`` to the value it had + when ``cmake`` launched (or unsets it), not to the most recent + ``NAME=VALUE`` option. + + .. option:: -- + + .. versionadded:: 3.24 - .. versionadded:: 3.24 Added support for the double dash argument ``--``. Use ``--`` to stop interpreting options/environment variables and treat the next argument as the command, even if it start with ``-`` or contains a ``=``. -``environment`` +.. program:: cmake-E + +.. option:: environment + Display the current environment variables. -``false`` +.. option:: false + .. versionadded:: 3.16 Do nothing, with an exit code of 1. -``make_directory <dir>...`` +.. option:: make_directory <dir>... + Create ``<dir>`` directories. If necessary, create parent directories too. If a directory already exists it will be silently ignored. @@ -805,13 +971,15 @@ Available commands are: .. versionadded:: 3.5 Support for multiple input directories. -``md5sum <file>...`` +.. option:: md5sum <file>... + Create MD5 checksum of files in ``md5sum`` compatible format:: 351abe79cd3800b38cdfb25d45015a15 file1.txt 052f86c15bbde68af55c7f7b340ab639 file2.txt -``sha1sum <file>...`` +.. option:: sha1sum <file>... + .. versionadded:: 3.10 Create SHA1 checksum of files in ``sha1sum`` compatible format:: @@ -819,7 +987,8 @@ Available commands are: 4bb7932a29e6f73c97bb9272f2bdc393122f86e0 file1.txt 1df4c8f318665f9a5f2ed38f55adadb7ef9f559c file2.txt -``sha224sum <file>...`` +.. option:: sha224sum <file>... + .. versionadded:: 3.10 Create SHA224 checksum of files in ``sha224sum`` compatible format:: @@ -827,7 +996,8 @@ Available commands are: b9b9346bc8437bbda630b0b7ddfc5ea9ca157546dbbf4c613192f930 file1.txt 6dfbe55f4d2edc5fe5c9197bca51ceaaf824e48eba0cc453088aee24 file2.txt -``sha256sum <file>...`` +.. option:: sha256sum <file>... + .. versionadded:: 3.10 Create SHA256 checksum of files in ``sha256sum`` compatible format:: @@ -835,7 +1005,8 @@ Available commands are: 76713b23615d31680afeb0e9efe94d47d3d4229191198bb46d7485f9cb191acc file1.txt 15b682ead6c12dedb1baf91231e1e89cfc7974b3787c1e2e01b986bffadae0ea file2.txt -``sha384sum <file>...`` +.. option:: sha384sum <file>... + .. versionadded:: 3.10 Create SHA384 checksum of files in ``sha384sum`` compatible format:: @@ -843,7 +1014,8 @@ Available commands are: acc049fedc091a22f5f2ce39a43b9057fd93c910e9afd76a6411a28a8f2b8a12c73d7129e292f94fc0329c309df49434 file1.txt 668ddeb108710d271ee21c0f3acbd6a7517e2b78f9181c6a2ff3b8943af92b0195dcb7cce48aa3e17893173c0a39e23d file2.txt -``sha512sum <file>...`` +.. option:: sha512sum <file>... + .. versionadded:: 3.10 Create SHA512 checksum of files in ``sha512sum`` compatible format:: @@ -851,7 +1023,8 @@ Available commands are: 2a78d7a6c5328cfb1467c63beac8ff21794213901eaadafd48e7800289afbc08e5fb3e86aa31116c945ee3d7bf2a6194489ec6101051083d1108defc8e1dba89 file1.txt 7a0b54896fe5e70cca6dd643ad6f672614b189bf26f8153061c4d219474b05dad08c4e729af9f4b009f1a1a280cb625454bf587c690f4617c27e3aebdf3b7a2d file2.txt -``remove [-f] <file>...`` +.. option:: remove [-f] <file>... + .. deprecated:: 3.17 Remove the file(s). The planned behavior was that if any of the @@ -864,7 +1037,8 @@ Available commands are: The implementation was buggy and always returned 0. It cannot be fixed without breaking backwards compatibility. Use ``rm`` instead. -``remove_directory <dir>...`` +.. option:: remove_directory <dir>... + .. deprecated:: 3.17 Remove ``<dir>`` directories and their contents. If a directory does @@ -877,11 +1051,13 @@ Available commands are: .. versionadded:: 3.16 If ``<dir>`` is a symlink to a directory, just the symlink will be removed. -``rename <oldname> <newname>`` +.. option:: rename <oldname> <newname> + Rename a file or directory (on one volume). If file with the ``<newname>`` name already exists, then it will be silently replaced. -``rm [-rRf] [--] <file|dir>...`` +.. option:: rm [-rRf] [--] <file|dir>... + .. versionadded:: 3.17 Remove the files ``<file>`` or directories ``<dir>``. @@ -892,22 +1068,29 @@ Available commands are: situations instead. Use ``--`` to stop interpreting options and treat all remaining arguments as paths, even if they start with ``-``. -``server`` +.. option:: server + Launch :manual:`cmake-server(7)` mode. -``sleep <number>...`` +.. option:: sleep <number>... + .. versionadded:: 3.0 Sleep for given number of seconds. -``tar [cxt][vf][zjJ] file.tar [<options>] [--] [<pathname>...]`` +.. option:: tar [cxt][vf][zjJ] file.tar [<options>] [--] [<pathname>...] + Create or extract a tar or zip archive. Options are: - ``c`` + .. program:: cmake-E_tar + + .. option:: c + Create a new archive containing the specified files. If used, the ``<pathname>...`` argument is mandatory. - ``x`` + .. option:: x + Extract to disk from the archive. .. versionadded:: 3.15 @@ -916,33 +1099,40 @@ Available commands are: When extracting selected files or directories, you must provide their exact names including the path, as printed by list (``-t``). - ``t`` + .. option:: t + List archive contents. .. versionadded:: 3.15 The ``<pathname>...`` argument could be used to list only selected files or directories. - ``v`` + .. option:: v + Produce verbose output. - ``z`` + .. option:: z + Compress the resulting archive with gzip. - ``j`` + .. option:: j + Compress the resulting archive with bzip2. - ``J`` + .. option:: J + .. versionadded:: 3.1 Compress the resulting archive with XZ. - ``--zstd`` + .. option:: --zstd + .. versionadded:: 3.15 Compress the resulting archive with Zstandard. - ``--files-from=<file>`` + .. option:: --files-from=<file> + .. versionadded:: 3.1 Read file names from the given file, one per line. @@ -950,25 +1140,29 @@ Available commands are: except for ``--add-file=<name>`` to add files whose names start in ``-``. - ``--format=<format>`` + .. option:: --format=<format> + .. versionadded:: 3.3 Specify the format of the archive to be created. Supported formats are: ``7zip``, ``gnutar``, ``pax``, ``paxr`` (restricted pax, default), and ``zip``. - ``--mtime=<date>`` + .. option:: --mtime=<date> + .. versionadded:: 3.1 Specify modification time recorded in tarball entries. - ``--touch`` + .. option:: --touch + .. versionadded:: 3.24 Use current local timestamp instead of extracting file timestamps from the archive. - ``--`` + .. option:: -- + .. versionadded:: 3.1 Stop interpreting options and treat all remaining arguments @@ -983,7 +1177,10 @@ Available commands are: ``tar`` tool. The command now also parses all flags, and if an invalid flag was provided, a warning is issued. -``time <command> [<args>...]`` +.. program:: cmake-E + +.. option:: time <command> [<args>...] + Run command and display elapsed time. .. versionadded:: 3.5 @@ -991,15 +1188,18 @@ Available commands are: through to the child process. This may break scripts that worked around the bug with their own extra quoting or escaping. -``touch <file>...`` +.. option:: touch <file>... + Creates ``<file>`` if file do not exist. If ``<file>`` exists, it is changing ``<file>`` access and modification times. -``touch_nocreate <file>...`` +.. option:: touch_nocreate <file>... + Touch a file if it exists but do not create it. If a file does not exist it will be silently ignored. -``true`` +.. option:: true + .. versionadded:: 3.16 Do nothing, with an exit code of 0. @@ -1009,28 +1209,34 @@ Windows-specific Command-Line Tools The following ``cmake -E`` commands are available only on Windows: -``delete_regv <key>`` +.. option:: delete_regv <key> + Delete Windows registry value. -``env_vs8_wince <sdkname>`` +.. option:: env_vs8_wince <sdkname> + .. versionadded:: 3.2 Displays a batch file which sets the environment for the provided Windows CE SDK installed in VS2005. -``env_vs9_wince <sdkname>`` +.. option:: env_vs9_wince <sdkname> + .. versionadded:: 3.2 Displays a batch file which sets the environment for the provided Windows CE SDK installed in VS2008. -``write_regv <key> <value>`` +.. option:: write_regv <key> <value> + Write Windows registry value. Run the Find-Package Tool ========================= +.. program:: cmake--find-package + CMake provides a pkg-config like helper for Makefile-based projects: .. code-block:: shell @@ -1046,10 +1252,45 @@ autoconf-based projects (via ``share/aclocal/cmake.m4``). This mode is not well-supported due to some technical limitations. It is kept for compatibility but should not be used in new projects. +.. _`Workflow Mode`: + +Run a Workflow Preset +===================== + +.. program:: cmake + +:manual:`CMake Presets <cmake-presets(7)>` provides a way to execute multiple +build steps in order: + +.. code-block:: shell + + cmake --workflow [<options>] + +The options are: + +.. option:: --workflow + + Select a :ref:`Workflow Preset` using one of the following options. + +.. program:: cmake--workflow + +.. option:: --preset <preset>, --preset=<preset> + + Use a workflow preset to specify a workflow. The project binary directory + is inferred from the initial configure preset. The current working directory + must contain CMake preset files. + See :manual:`preset <cmake-presets(7)>` for more details. + +.. option:: --list-presets + + Lists the available workflow presets. The current working directory must + contain CMake preset files. View Help ========= +.. program:: cmake + To print selected pages from the CMake documentation, use .. code-block:: shell diff --git a/Help/manual/cpack.1.rst b/Help/manual/cpack.1.rst index 395cd41..3f26d72 100644 --- a/Help/manual/cpack.1.rst +++ b/Help/manual/cpack.1.rst @@ -26,12 +26,12 @@ All supported generators are specified in the :manual:`cpack-generators <cpack-generators(7)>` manual. The command ``cpack --help`` prints a list of generators supported for the target platform. Which of them are to be used can be selected through the :variable:`CPACK_GENERATOR` variable -or through the command-line option ``-G``. +or through the command-line option :option:`-G <cpack -G>`. The **cpack** program is steered by a configuration file written in the :manual:`CMake language <cmake-language(7)>`. Unless chosen differently -through the command-line option ``--config``, the file ``CPackConfig.cmake`` -in the current directory is used. +through the command-line option :option:`--config <cpack --config>`, the +file ``CPackConfig.cmake`` in the current directory is used. In the standard CMake workflow, the file ``CPackConfig.cmake`` is generated by the :manual:`cmake <cmake(1)>` executable, provided the :module:`CPack` @@ -40,7 +40,10 @@ module is included by the project's ``CMakeLists.txt`` file. Options ======= -``-G <generators>`` +.. program:: cpack + +.. option:: -G <generators> + ``<generators>`` is a :ref:`semicolon-separated list <CMake Language Lists>` of generator names. ``cpack`` will iterate through this list and produce package(s) in that generator's format according to the details provided in @@ -48,7 +51,8 @@ Options the :variable:`CPACK_GENERATOR` variable determines the default set of generators that will be used. -``-C <configs>`` +.. option:: -C <configs> + Specify the project configuration(s) to be packaged (e.g. ``Debug``, ``Release``, etc.), where ``<configs>`` is a :ref:`semicolon-separated list <CMake Language Lists>`. @@ -58,36 +62,44 @@ Options The user is responsible for ensuring that the configuration(s) listed have already been built before invoking ``cpack``. -``-D <var>=<value>`` +.. option:: -D <var>=<value> + Set a CPack variable. This will override any value set for ``<var>`` in the input file read by ``cpack``. -``--config <configFile>`` +.. option:: --config <configFile> + Specify the configuration file read by ``cpack`` to provide the packaging details. By default, ``CPackConfig.cmake`` in the current directory will be used. -``--verbose, -V`` +.. option:: -V, --verbose + Run ``cpack`` with verbose output. This can be used to show more details from the package generation tools and is suitable for project developers. -``--debug`` +.. option:: --debug + Run ``cpack`` with debug output. This option is intended mainly for the developers of ``cpack`` itself and is not normally needed by project developers. -``--trace`` +.. option:: --trace + Put the underlying cmake scripts in trace mode. -``--trace-expand`` +.. option:: --trace-expand + Put the underlying cmake scripts in expanded trace mode. -``-P <packageName>`` +.. option:: -P <packageName> + Override/define the value of the :variable:`CPACK_PACKAGE_NAME` variable used for packaging. Any value set for this variable in the ``CPackConfig.cmake`` file will then be ignored. -``-R <packageVersion>`` +.. option:: -R <packageVersion> + Override/define the value of the :variable:`CPACK_PACKAGE_VERSION` variable used for packaging. It will override a value set in the ``CPackConfig.cmake`` file or one automatically computed from @@ -95,16 +107,26 @@ Options :variable:`CPACK_PACKAGE_VERSION_MINOR` and :variable:`CPACK_PACKAGE_VERSION_PATCH`. -``-B <packageDirectory>`` +.. option:: -B <packageDirectory> + Override/define :variable:`CPACK_PACKAGE_DIRECTORY`, which controls the directory where CPack will perform its packaging work. The resultant package(s) will be created at this location by default and a ``_CPack_Packages`` subdirectory will also be created below this directory to use as a working area during package creation. -``--vendor <vendorName>`` +.. option:: --vendor <vendorName> + Override/define :variable:`CPACK_PACKAGE_VENDOR`. +.. option:: --preset <presetName> + + Use a preset from :manual:`cmake-presets(7)`. + +.. option:: --list-presets + + List presets from :manual:`cmake-presets(7)`. + .. include:: OPTIONS_HELP.txt See Also diff --git a/Help/manual/ctest.1.rst b/Help/manual/ctest.1.rst index 06f0d4e..3497a9f 100644 --- a/Help/manual/ctest.1.rst +++ b/Help/manual/ctest.1.rst @@ -10,12 +10,24 @@ Synopsis .. parsed-literal:: - ctest [<options>] - ctest --build-and-test <path-to-source> <path-to-build> - --build-generator <generator> [<options>...] - [--build-options <opts>...] [--test-command <command> [<args>...]] - ctest {-D <dashboard> | -M <model> -T <action> | -S <script> | -SP <script>} - [-- <dashboard-options>...] + `Run Tests`_ + ctest [<options>] + + `Build and Test Mode`_ + ctest --build-and-test <path-to-source> <path-to-build> + --build-generator <generator> [<options>...] + [--build-options <opts>...] + [--test-command <command> [<args>...]] + + `Dashboard Client`_ + ctest -D <dashboard> [-- <dashboard-options>...] + ctest -M <model> -T <action> [-- <dashboard-options>...] + ctest -S <script> [-- <dashboard-options>...] + ctest -SP <script> [-- <dashboard-options>...] + + `View Help`_ + ctest --help[-<topic>] + Description =========== @@ -25,22 +37,27 @@ CMake-generated build trees created for projects that use the :command:`enable_testing` and :command:`add_test` commands have testing support. This program will run the tests and report results. -.. _`CTest Options`: +.. _`Run Tests`: -Options -======= +Run Tests +========= + +.. program:: ctest + +.. option:: --preset <preset>, --preset=<preset> -``--preset <preset>``, ``--preset=<preset>`` Use a test preset to specify test options. The project binary directory is inferred from the ``configurePreset`` key. The current working directory must contain CMake preset files. See :manual:`preset <cmake-presets(7)>` for more details. -``--list-presets`` +.. option:: --list-presets + Lists the available test presets. The current working directory must contain CMake preset files. -``-C <cfg>, --build-config <cfg>`` +.. option:: -C <cfg>, --build-config <cfg> + Choose configuration to test. Some CMake-generated build trees can have multiple build @@ -48,7 +65,8 @@ Options which one should be tested. Example configurations are ``Debug`` and ``Release``. -``--progress`` +.. option:: --progress + Enable short progress output from tests. When the output of **ctest** is being sent directly to a terminal, the @@ -61,40 +79,47 @@ Options This option can also be enabled by setting the environment variable :envvar:`CTEST_PROGRESS_OUTPUT`. -``-V,--verbose`` +.. option:: -V, --verbose + Enable verbose output from tests. Test output is normally suppressed and only summary information is displayed. This option will show all test output. -``-VV,--extra-verbose`` +.. option:: -VV, --extra-verbose + Enable more verbose output from tests. Test output is normally suppressed and only summary information is displayed. This option will show even more test output. -``--debug`` +.. option:: --debug + Displaying more verbose internals of CTest. This feature will result in a large number of output that is mostly useful for debugging dashboard problems. -``--output-on-failure`` +.. option:: --output-on-failure + Output anything outputted by the test program if the test should fail. This option can also be enabled by setting the :envvar:`CTEST_OUTPUT_ON_FAILURE` environment variable -``--stop-on-failure`` +.. option:: --stop-on-failure + Stop running the tests when the first failure happens. -``-F`` +.. option:: -F + Enable failover. This option allows CTest to resume a test set execution that was previously interrupted. If no interruption occurred, the ``-F`` option will have no effect. -``-j <jobs>, --parallel <jobs>`` +.. option:: -j <jobs>, --parallel <jobs> + Run the tests in parallel using the given number of jobs. This option tells CTest to run the tests in parallel using given @@ -105,7 +130,8 @@ Options See `Label and Subproject Summary`_. -``--resource-spec-file <file>`` +.. option:: --resource-spec-file <file> + Run CTest with :ref:`resource allocation <ctest-resource-allocation>` enabled, using the :ref:`resource specification file <ctest-resource-specification-file>` @@ -114,40 +140,54 @@ Options When ``ctest`` is run as a `Dashboard Client`_ this sets the ``ResourceSpecFile`` option of the `CTest Test Step`_. -``--test-load <level>`` - While running tests in parallel (e.g. with ``-j``), try not to start - tests when they may cause the CPU load to pass above a given threshold. +.. option:: --test-load <level> + + While running tests in parallel (e.g. with :option:`-j <ctest -j>`), try + not to start tests when they may cause the CPU load to pass above a given + threshold. When ``ctest`` is run as a `Dashboard Client`_ this sets the ``TestLoad`` option of the `CTest Test Step`_. -``-Q,--quiet`` +.. option:: -Q, --quiet + Make CTest quiet. This option will suppress all the output. The output log file will - still be generated if the ``--output-log`` is specified. Options such - as ``--verbose``, ``--extra-verbose``, and ``--debug`` are ignored + still be generated if the :option:`--output-log <ctest --output-log>` is + specified. Options such as :option:`--verbose <ctest --verbose>`, + :option:`--extra-verbose <ctest --extra-verbose>`, and + :option:`--debug <ctest --debug>` are ignored if ``--quiet`` is specified. -``-O <file>, --output-log <file>`` +.. option:: -O <file>, --output-log <file> + Output to log file. This option tells CTest to write all its output to a ``<file>`` log file. -``--output-junit <file>`` +.. option:: --output-junit <file> + + .. versionadded:: 3.21 + Write test results in JUnit format. This option tells CTest to write test results to ``<file>`` in JUnit XML format. If ``<file>`` already exists, it will be overwritten. If using the - ``-S`` option to run a dashboard script, use the ``OUTPUT_JUNIT`` keyword - with the :command:`ctest_test` command instead. + :option:`-S <ctest -S>` option to run a dashboard script, use the + ``OUTPUT_JUNIT`` keyword with the :command:`ctest_test` command instead. + +.. option:: -N, --show-only[=<format>] -``-N,--show-only[=<format>]`` Disable actual execution of tests. This option tells CTest to list the tests that would be run but not - actually run them. Useful in conjunction with the ``-R`` and ``-E`` - options. + actually run them. Useful in conjunction with the :option:`-R <ctest -R>` + and :option:`-E <ctest -E>` options. + + .. versionadded:: 3.14 + + The ``--show-only`` option accepts a ``<format>`` value. ``<format>`` can be one of the following values. @@ -159,7 +199,8 @@ Options Dump the test information in JSON format. See `Show as JSON Object Model`_. -``-L <regex>, --label-regex <regex>`` +.. option:: -L <regex>, --label-regex <regex> + Run tests with labels matching regular expression as described under :ref:`string(REGEX) <Regex Specification>`. @@ -169,19 +210,22 @@ Options of the test's labels (i.e. the multiple ``-L`` labels form an ``AND`` relationship). See `Label Matching`_. -``-R <regex>, --tests-regex <regex>`` +.. option:: -R <regex>, --tests-regex <regex> + Run tests matching regular expression. This option tells CTest to run only the tests whose names match the given regular expression. -``-E <regex>, --exclude-regex <regex>`` +.. option:: -E <regex>, --exclude-regex <regex> + Exclude tests matching regular expression. This option tells CTest to NOT run the tests whose names match the given regular expression. -``-LE <regex>, --label-exclude <regex>`` +.. option:: -LE <regex>, --label-exclude <regex> + Exclude tests with labels matching regular expression. This option tells CTest to NOT run the tests whose labels match the @@ -190,7 +234,8 @@ Options of the test's labels (i.e. the multiple ``-LE`` labels form an ``AND`` relationship). See `Label Matching`_. -``-FA <regex>, --fixture-exclude-any <regex>`` +.. option:: -FA <regex>, --fixture-exclude-any <regex> + Exclude fixtures matching ``<regex>`` from automatically adding any tests to the test set. @@ -201,72 +246,18 @@ Options including test dependencies and skipping tests that have fixture setup tests that fail. -``-FS <regex>, --fixture-exclude-setup <regex>`` - Same as ``-FA`` except only matching setup tests are excluded. - -``-FC <regex>, --fixture-exclude-cleanup <regex>`` - Same as ``-FA`` except only matching cleanup tests are excluded. - -``-D <dashboard>, --dashboard <dashboard>`` - Execute dashboard test. - - This option tells CTest to act as a CDash client and perform a - dashboard test. All tests are ``<Mode><Test>``, where ``<Mode>`` can be - ``Experimental``, ``Nightly``, and ``Continuous``, and ``<Test>`` can be - ``Start``, ``Update``, ``Configure``, ``Build``, ``Test``, - ``Coverage``, and ``Submit``. - - See `Dashboard Client`_. - -``-D <var>:<type>=<value>`` - Define a variable for script mode. - - Pass in variable values on the command line. Use in conjunction - with ``-S`` to pass variable values to a dashboard script. Parsing ``-D`` - arguments as variable values is only attempted if the value - following ``-D`` does not match any of the known dashboard types. - -``-M <model>, --test-model <model>`` - Sets the model for a dashboard. - - This option tells CTest to act as a CDash client where the ``<model>`` - can be ``Experimental``, ``Nightly``, and ``Continuous``. - Combining ``-M`` and ``-T`` is similar to ``-D``. +.. option:: -FS <regex>, --fixture-exclude-setup <regex> - See `Dashboard Client`_. + Same as :option:`-FA <ctest -FA>` except only matching setup tests are + excluded. -``-T <action>, --test-action <action>`` - Sets the dashboard action to perform. - - This option tells CTest to act as a CDash client and perform some - action such as ``start``, ``build``, ``test`` etc. See - `Dashboard Client Steps`_ for the full list of actions. - Combining ``-M`` and ``-T`` is similar to ``-D``. +.. option:: -FC <regex>, --fixture-exclude-cleanup <regex> - See `Dashboard Client`_. + Same as :option:`-FA <ctest -FA>` except only matching cleanup tests are + excluded. -``-S <script>, --script <script>`` - Execute a dashboard for a configuration. +.. option:: -I [Start,End,Stride,test#,test#|Test file], --tests-information - This option tells CTest to load in a configuration script which sets - a number of parameters such as the binary and source directories. - Then CTest will do what is required to create and run a dashboard. - This option basically sets up a dashboard and then runs ``ctest -D`` - with the appropriate options. - - See `Dashboard Client`_. - -``-SP <script>, --script-new-process <script>`` - Execute a dashboard for a configuration. - - This option does the same operations as ``-S`` but it will do them in a - separate process. This is primarily useful in cases where the - script may modify the environment and you do not want the modified - environment to impact other ``-S`` scripts. - - See `Dashboard Client`_. - -``-I [Start,End,Stride,test#,test#|Test file], --tests-information`` Run a specific number of tests by number. This option causes CTest to run tests starting at number ``Start``, @@ -275,23 +266,29 @@ Options ``End``, or ``Stride`` can be empty. Optionally a file can be given that contains the same syntax as the command line. -``-U, --union`` - Take the Union of ``-I`` and ``-R``. +.. option:: -U, --union + + Take the Union of :option:`-I <ctest -I>` and :option:`-R <ctest -R>`. + + When both :option:`-R <ctest -R>` and :option:`-I <ctest -I>` are specified + by default the intersection of tests are run. By specifying ``-U`` the union + of tests is run instead. - When both ``-R`` and ``-I`` are specified by default the intersection of - tests are run. By specifying ``-U`` the union of tests is run instead. +.. option:: --rerun-failed -``--rerun-failed`` Run only the tests that failed previously. This option tells CTest to perform only the tests that failed during its previous run. When this option is specified, CTest ignores all - other options intended to modify the list of tests to run (``-L``, ``-R``, - ``-E``, ``-LE``, ``-I``, etc). In the event that CTest runs and no tests - fail, subsequent calls to CTest with the ``--rerun-failed`` option will run - the set of tests that most recently failed (if any). + other options intended to modify the list of tests to run ( + :option:`-L <ctest -L>`, :option:`-R <ctest -R>`, :option:`-E <ctest -E>`, + :option:`-LE <ctest -LE>`, :option:`-I <ctest -I>`, etc). In the event that + CTest runs and no tests fail, subsequent calls to CTest with the + ``--rerun-failed`` option will run the set of tests that most recently + failed (if any). + +.. option:: --repeat <mode>:<n> -``--repeat <mode>:<n>`` Run tests repeatedly based on the given ``<mode>`` up to ``<n>`` times. The modes are: @@ -310,17 +307,20 @@ Options This is useful in tolerating sporadic timeouts in test cases on busy machines. -``--repeat-until-fail <n>`` - Equivalent to ``--repeat until-fail:<n>``. +.. option:: --repeat-until-fail <n> + + Equivalent to :option:`--repeat until-fail:\<n\> <ctest --repeat>`. + +.. option:: --max-width <width> -``--max-width <width>`` Set the max width for a test name to output. Set the maximum width for each test name to show in the output. This allows the user to widen the output to avoid clipping the test name which can be very annoying. -``--interactive-debug-mode [0|1]`` +.. option:: --interactive-debug-mode [0|1] + Set the interactive mode to ``0`` or ``1``. This option causes CTest to run tests in either an interactive mode @@ -332,7 +332,8 @@ Options popup windows to appear. Now, due to CTest's use of ``libuv`` to launch test processes, all system debug popup windows are always blocked. -``--no-label-summary`` +.. option:: --no-label-summary + Disable timing summary information for labels. This option tells CTest not to print summary information for each @@ -341,7 +342,8 @@ Options See `Label and Subproject Summary`_. -``--no-subproject-summary`` +.. option:: --no-subproject-summary + Disable timing summary information for subprojects. This option tells CTest not to print summary information for each @@ -350,79 +352,95 @@ Options See `Label and Subproject Summary`_. -``--build-and-test`` -See `Build and Test Mode`_. +.. option:: --test-dir <dir> + + Specify the directory in which to look for tests. -``--test-dir <dir>`` -Specify the directory in which to look for tests. +.. option:: --test-output-size-passed <size> -``--test-output-size-passed <size>`` .. versionadded:: 3.4 Limit the output for passed tests to ``<size>`` bytes. -``--test-output-size-failed <size>`` +.. option:: --test-output-size-failed <size> + .. versionadded:: 3.4 Limit the output for failed tests to ``<size>`` bytes. -``--test-output-truncation <mode>`` +.. option:: --test-output-truncation <mode> + .. versionadded:: 3.24 Truncate ``tail`` (default), ``middle`` or ``head`` of test output once maximum output size is reached. -``--overwrite`` +.. option:: --overwrite + Overwrite CTest configuration option. By default CTest uses configuration options from configuration file. This option will overwrite the configuration option. -``--force-new-ctest-process`` +.. option:: --force-new-ctest-process + Run child CTest instances as new processes. By default CTest will run child CTest instances within the same process. If this behavior is not desired, this argument will enforce new processes for child CTest processes. -``--schedule-random`` +.. option:: --schedule-random + Use a random order for scheduling tests. This option will run the tests in a random order. It is commonly used to detect implicit dependencies in a test suite. -``--submit-index`` +.. option:: --submit-index + Legacy option for old Dart2 dashboard server feature. Do not use. -``--timeout <seconds>`` +.. option:: --timeout <seconds> + Set the default test timeout. This option effectively sets a timeout on all tests that do not already have a timeout set on them via the :prop_test:`TIMEOUT` property. -``--stop-time <time>`` +.. option:: --stop-time <time> + Set a time at which all tests should stop running. Set a real time of day at which all tests should timeout. Example: ``7:00:00 -0400``. Any time format understood by the curl date parser is accepted. Local time is assumed if no timezone is specified. -``--print-labels`` +.. option:: --print-labels + Print all available test labels. This option will not run any tests, it will simply print the list of all labels associated with the test set. -``--no-tests=<[error|ignore]>`` - Regard no tests found either as error or ignore it. +.. option:: --no-tests=<action> + + Regard no tests found either as error (when ``<action>`` is set to + ``error``) or ignore it (when ``<action>`` is set to ``ignore``). If no tests were found, the default behavior of CTest is to always log an error message but to return an error code in script mode only. This option unifies the behavior of CTest by either returning an error code if no tests were found or by ignoring it. +View Help +========= + +To print version details or selected pages from the CMake documentation, +use one of the following options: + .. include:: OPTIONS_HELP.txt .. _`Label Matching`: @@ -435,17 +453,17 @@ or excluded from a test run by filtering on the labels. Each individual filter is a regular expression applied to the labels attached to a test. -When ``-L`` is used, in order for a test to be included in a +When :option:`-L <ctest -L>` is used, in order for a test to be included in a test run, each regular expression must match at least one -label. Using more than one ``-L`` option means "match **all** +label. Using more than one :option:`-L <ctest -L>` option means "match **all** of these". -The ``-LE`` option works just like ``-L``, but excludes tests -rather than including them. A test is excluded if each regular -expression matches at least one label. +The :option:`-LE <ctest -LE>` option works just like :option:`-L <ctest -L>`, +but excludes tests rather than including them. A test is excluded if each +regular expression matches at least one label. -If a test has no labels attached to it, then ``-L`` will never -include that test, and ``-LE`` will never exclude that test. +If a test has no labels attached to it, then :option:`-L <ctest -L>` will never +include that test, and :option:`-LE <ctest -LE>` will never exclude that test. As an example of tests with labels, consider five tests, with the following labels: @@ -532,62 +550,85 @@ be provided to use ``--build-and-test``. If ``--test-command`` is specified then that will be run after the build is complete. Other options that affect this mode include: -``--build-target`` - Specify a specific target to build. +.. option:: --build-and-test - If left out the ``all`` target is built. + Switch into the build and test mode. + +.. option:: --build-target + + Specify a specific target to build. The option can be given multiple times + with different targets, in which case each target is built in turn. + A clean will be done before building each target unless the + :option:`--build-noclean` option is given. + + If no ``--build-target`` is specified, the ``all`` target is built. + +.. option:: --build-nocmake -``--build-nocmake`` Run the build without running cmake first. Skip the cmake step. -``--build-run-dir`` +.. option:: --build-run-dir + Specify directory to run programs from. Directory where programs will be after it has been compiled. -``--build-two-config`` +.. option:: --build-two-config + Run CMake twice. -``--build-exe-dir`` +.. option:: --build-exe-dir + Specify the directory for the executable. -``--build-generator`` +.. option:: --build-generator + Specify the generator to use. See the :manual:`cmake-generators(7)` manual. -``--build-generator-platform`` +.. option:: --build-generator-platform + Specify the generator-specific platform. -``--build-generator-toolset`` +.. option:: --build-generator-toolset + Specify the generator-specific toolset. -``--build-project`` +.. option:: --build-project + Specify the name of the project to build. -``--build-makeprogram`` +.. option:: --build-makeprogram + Specify the explicit make program to be used by CMake when configuring and building the project. Only applicable for Make and Ninja based generators. -``--build-noclean`` +.. option:: --build-noclean + Skip the make clean step. -``--build-config-sample`` +.. option:: --build-config-sample + A sample executable to use to determine the configuration that should be used. e.g. ``Debug``, ``Release`` etc. -``--build-options`` +.. option:: --build-options + Additional options for configuring the build (i.e. for CMake, not for the build tool). Note that if this is specified, the ``--build-options`` keyword and its arguments must be the last option given on the command line, with the possible exception of ``--test-command``. -``--test-command`` - The command to run as the test step with the ``--build-and-test`` option. +.. option:: --test-command + + The command to run as the test step with the + :option:`--build-and-test <ctest --build-and-test>` option. All arguments following this keyword will be assumed to be part of the test command line, so it must be the last option given. -``--test-timeout`` +.. option:: --test-timeout + The time limit in seconds .. _`Dashboard Client`: @@ -600,12 +641,80 @@ application. As a dashboard client, CTest performs a sequence of steps to configure, build, and test software, and then submits the results to a `CDash`_ server. The command-line signature used to submit to `CDash`_ is:: - ctest (-D <dashboard> | -M <model> -T <action> | -S <script> | -SP <script>) - [-- <dashboard-options>...] + ctest -D <dashboard> [-- <dashboard-options>...] + ctest -M <model> -T <action> [-- <dashboard-options>...] + ctest -S <script> [-- <dashboard-options>...] + ctest -SP <script> [-- <dashboard-options>...] Options for Dashboard Client include: -``--group <group>`` +.. option:: -D <dashboard>, --dashboard <dashboard> + + Execute dashboard test. + + This option tells CTest to act as a CDash client and perform a + dashboard test. All tests are ``<Mode><Test>``, where ``<Mode>`` can be + ``Experimental``, ``Nightly``, and ``Continuous``, and ``<Test>`` can be + ``Start``, ``Update``, ``Configure``, ``Build``, ``Test``, + ``Coverage``, and ``Submit``. + + If ``<dashboard>`` is not one of the recognized ``<Mode><Test>`` values, + this will be treated as a variable definition instead (see the + :ref:`dashboard-options <Dashboard Options>` further below). + +.. option:: -M <model>, --test-model <model> + + Sets the model for a dashboard. + + This option tells CTest to act as a CDash client where the ``<model>`` + can be ``Experimental``, ``Nightly``, and ``Continuous``. + Combining ``-M`` and :option:`-T <ctest -T>` is similar to + :option:`-D <ctest -D>`. + +.. option:: -T <action>, --test-action <action> + + Sets the dashboard action to perform. + + This option tells CTest to act as a CDash client and perform some + action such as ``start``, ``build``, ``test`` etc. See + `Dashboard Client Steps`_ for the full list of actions. + Combining :option:`-M <ctest -M>` and ``-T`` is similar to + :option:`-D <ctest -D>`. + +.. option:: -S <script>, --script <script> + + Execute a dashboard for a configuration. + + This option tells CTest to load in a configuration script which sets + a number of parameters such as the binary and source directories. + Then CTest will do what is required to create and run a dashboard. + This option basically sets up a dashboard and then runs :option:`ctest -D` + with the appropriate options. + +.. option:: -SP <script>, --script-new-process <script> + + Execute a dashboard for a configuration. + + This option does the same operations as :option:`-S <ctest -S>` but it + will do them in a separate process. This is primarily useful in cases + where the script may modify the environment and you do not want the modified + environment to impact other :option:`-S <ctest -S>` scripts. + +.. _`Dashboard Options`: + +The available ``<dashboard-options>`` are the following: + +.. option:: -D <var>:<type>=<value> + + Define a variable for script mode. + + Pass in variable values on the command line. Use in conjunction + with :option:`-S <ctest -S>` to pass variable values to a dashboard script. + Parsing ``-D`` arguments as variable values is only attempted if the value + following ``-D`` does not match any of the known dashboard types. + +.. option:: --group <group> + Specify what group you'd like to submit results to Submit dashboard to specified group instead of default one. By @@ -616,29 +725,34 @@ Options for Dashboard Client include: This replaces the deprecated option ``--track``. Despite the name change its behavior is unchanged. -``-A <file>, --add-notes <file>`` +.. option:: -A <file>, --add-notes <file> + Add a notes file with submission. This option tells CTest to include a notes file when submitting dashboard. -``--tomorrow-tag`` +.. option:: --tomorrow-tag + ``Nightly`` or ``Experimental`` starts with next day tag. This is useful if the build will not finish in one day. -``--extra-submit <file>[;<file>]`` +.. option:: --extra-submit <file>[;<file>] + Submit extra files to the dashboard. This option will submit extra files to the dashboard. -``--http1.0`` +.. option:: --http1.0 + Submit using `HTTP 1.0`. This option will force CTest to use `HTTP 1.0` to submit files to the dashboard, instead of `HTTP 1.1`. -``--no-compress-output`` +.. option:: --no-compress-output + Do not compress test output when submitting. This flag will turn off automatic compression of test output. Use @@ -722,7 +836,7 @@ Run the ``ctest`` command with the current working directory set to the build tree and use one of these signatures:: ctest -D <mode>[<step>] - ctest -M <mode> [ -T <step> ]... + ctest -M <mode> [-T <step>]... The ``<mode>`` must be one of the above `Dashboard Client Modes`_, and each ``<step>`` must be one of the above `Dashboard Client Steps`_. @@ -1027,9 +1141,9 @@ Configuration settings include: ``DefaultCTestConfigurationType`` When the build system to be launched allows build-time selection of the configuration (e.g. ``Debug``, ``Release``), this specifies - the default configuration to be built when no ``-C`` option is - given to the ``ctest`` command. The value will be substituted into - the value of ``MakeCommand`` to replace the literal string + the default configuration to be built when no :option:`-C <ctest -C>` + option is given to the ``ctest`` command. The value will be substituted + into the value of ``MakeCommand`` to replace the literal string ``${CTEST_CONFIGURATION_TYPE}`` if it appears. * `CTest Script`_ variable: :variable:`CTEST_CONFIGURATION_TYPE` @@ -1101,8 +1215,9 @@ Configuration settings include: See `Label and Subproject Summary`_. ``TestLoad`` - While running tests in parallel (e.g. with ``-j``), try not to start - tests when they may cause the CPU load to pass above a given threshold. + While running tests in parallel (e.g. with :option:`-j <ctest -j>`), + try not to start tests when they may cause the CPU load to pass above + a given threshold. * `CTest Script`_ variable: :variable:`CTEST_TEST_LOAD` * :module:`CTest` module variable: ``CTEST_TEST_LOAD`` @@ -1382,6 +1497,8 @@ Configuration settings include: Show as JSON Object Model ========================= +.. versionadded:: 3.14 + When the ``--show-only=json-v1`` command line option is given, the test information is output in JSON format. Version 1.0 of the JSON object model is defined as follows: @@ -1518,12 +1635,12 @@ Resource Specification File --------------------------- The resource specification file is a JSON file which is passed to CTest, either -on the :manual:`ctest(1)` command line as ``--resource-spec-file``, or as the +on the command line as :option:`ctest --resource-spec-file`, or as the ``RESOURCE_SPEC_FILE`` argument of :command:`ctest_test`. If a dashboard script is used and ``RESOURCE_SPEC_FILE`` is not specified, the value of :variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script is used instead. -If ``--resource-spec-file``, ``RESOURCE_SPEC_FILE``, and -:variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script are not specified, +If :option:`--resource-spec-file <ctest --resource-spec-file>`, ``RESOURCE_SPEC_FILE``, +and :variable:`CTEST_RESOURCE_SPEC_FILE` in the dashboard script are not specified, the value of :variable:`CTEST_RESOURCE_SPEC_FILE` in the CMake build is used instead. If none of these are specified, no resource spec file is used. diff --git a/Help/manual/presets/example.json b/Help/manual/presets/example.json index be5c791..696ab47 100644 --- a/Help/manual/presets/example.json +++ b/Help/manual/presets/example.json @@ -1,5 +1,5 @@ { - "version": 5, + "version": 6, "cmakeMinimumRequired": { "major": 3, "minor": 23, @@ -66,6 +66,38 @@ "execution": {"noTestsAction": "error", "stopOnFailure": true} } ], + "packagePresets": [ + { + "name": "default", + "configurePreset": "default", + "generators": [ + "TGZ" + ] + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + }, + { + "type": "package", + "name": "default" + } + ] + } + ], "vendor": { "example.com/ExampleIDE/1.0": { "autoFormat": false diff --git a/Help/manual/presets/schema.json b/Help/manual/presets/schema.json index c96405c..348116b 100644 --- a/Help/manual/presets/schema.json +++ b/Help/manual/presets/schema.json @@ -72,6 +72,23 @@ "include": { "$ref": "#/definitions/include"} }, "additionalProperties": false + }, + { + "properties": { + "version": { + "const": 6, + "description": "A required integer representing the version of the JSON schema." + }, + "cmakeMinimumRequired": { "$ref": "#/definitions/cmakeMinimumRequired"}, + "vendor": { "$ref": "#/definitions/vendor" }, + "configurePresets": { "$ref": "#/definitions/configurePresetsV3"}, + "buildPresets": { "$ref": "#/definitions/buildPresetsV4"}, + "testPresets": { "$ref": "#/definitions/testPresetsV6"}, + "packagePresets": { "$ref": "#/definitions/packagePresetsV6"}, + "workflowPresets": { "$ref": "#/definitions/workflowPresetsV6" }, + "include": { "$ref": "#/definitions/include"} + }, + "additionalProperties": false } ], "required": [ @@ -476,12 +493,12 @@ "properties": { "name": { "type": "string", - "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, or test) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", + "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", "minLength": 1 }, "hidden": { "type": "boolean", - "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument, will not show up in the CMake GUI, and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field." + "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field." }, "inherits": { "anyOf": [ @@ -688,6 +705,25 @@ "additionalProperties": false } }, + "testPresetsItemsV6": { + "type": "array", + "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 6 and higher.", + "items": { + "type": "object", + "properties": { + "output": { + "type": "object", + "description": "An optional object specifying output options.", + "properties": { + "outputJUnitFile": { + "type": "string", + "description": "An optional string specifying a path to a JUnit file. Equivalent to passing --output-junit on the command line." + } + } + } + } + } + }, "testPresetsItemsV5": { "type": "array", "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 5 and higher.", @@ -728,12 +764,12 @@ "properties": { "name": { "type": "string", - "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, or test) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", + "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", "minLength": 1 }, "hidden": { "type": "boolean", - "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument, will not show up in the CMake GUI, and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field." + "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field." }, "inherits": { "anyOf": [ @@ -1034,6 +1070,58 @@ ] } }, + "testPresetsV6": { + "type": "array", + "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 6 and higher.", + "allOf": [ + { "$ref": "#/definitions/testPresetsItemsV2" }, + { "$ref": "#/definitions/testPresetsItemsV3" }, + { "$ref": "#/definitions/testPresetsItemsV5" }, + { "$ref": "#/definitions/testPresetsItemsV6" } + ], + "items": { + "type": "object", + "properties": { + "name": {}, + "hidden": {}, + "inherits": {}, + "configurePreset": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "inheritConfigureEnvironment": {}, + "environment": {}, + "configuration": {}, + "overwriteConfigurationFile": {}, + "output": { + "type": "object", + "properties": { + "shortProgress": {}, + "verbosity": {}, + "debug": {}, + "outputOnFailure": {}, + "quiet": {}, + "outputLogFile": {}, + "outputJUnitFile": {}, + "labelSummary": {}, + "subprojectSummary": {}, + "maxPassedTestOutputSize": {}, + "maxFailedTestOutputSize": {}, + "maxTestNameWidth": {}, + "testOutputTruncation": {} + }, + "additionalProperties": false + }, + "filter": {}, + "execution": {}, + "condition": {} + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, "testPresetsV5": { "type": "array", "description": "An optional array of test preset objects. Used to specify arguments to ctest. Available in version 5 and higher.", @@ -1056,7 +1144,24 @@ "environment": {}, "configuration": {}, "overwriteConfigurationFile": {}, - "output": {}, + "output": { + "type": "object", + "properties": { + "shortProgress": {}, + "verbosity": {}, + "debug": {}, + "outputOnFailure": {}, + "quiet": {}, + "outputLogFile": {}, + "labelSummary": {}, + "subprojectSummary": {}, + "maxPassedTestOutputSize": {}, + "maxFailedTestOutputSize": {}, + "maxTestNameWidth": {}, + "testOutputTruncation": {} + }, + "additionalProperties": false + }, "filter": {}, "execution": {}, "condition": {} @@ -1088,7 +1193,23 @@ "environment": {}, "configuration": {}, "overwriteConfigurationFile": {}, - "output": {}, + "output": { + "type": "object", + "properties": { + "shortProgress": {}, + "verbosity": {}, + "debug": {}, + "outputOnFailure": {}, + "quiet": {}, + "outputLogFile": {}, + "labelSummary": {}, + "subprojectSummary": {}, + "maxPassedTestOutputSize": {}, + "maxFailedTestOutputSize": {}, + "maxTestNameWidth": {} + }, + "additionalProperties": false + }, "filter": {}, "execution": {}, "condition": {} @@ -1119,7 +1240,23 @@ "environment": {}, "configuration": {}, "overwriteConfigurationFile": {}, - "output": {}, + "output": { + "type": "object", + "properties": { + "shortProgress": {}, + "verbosity": {}, + "debug": {}, + "outputOnFailure": {}, + "quiet": {}, + "outputLogFile": {}, + "labelSummary": {}, + "subprojectSummary": {}, + "maxPassedTestOutputSize": {}, + "maxFailedTestOutputSize": {}, + "maxTestNameWidth": {} + }, + "additionalProperties": false + }, "filter": {}, "execution": {} }, @@ -1129,6 +1266,260 @@ "additionalProperties": false } }, + "packagePresetsItemsV6": { + "type": "array", + "description": "An optional array of package preset objects. Used to specify arguments to cpack. Available in version 6 and higher.", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", + "minLength": 1 + }, + "hidden": { + "type": "boolean", + "description": "An optional boolean specifying whether or not a preset should be hidden. If a preset is hidden, it cannot be used in the --preset argument and does not have to have a valid configurePreset, even from inheritance. Hidden presets are intended to be used as a base for other presets to inherit via the inherits field." + }, + "inherits": { + "anyOf": [ + { + "type": "string", + "description": "An optional string representing the name of the package preset to inherit from.", + "minLength": 1 + }, + { + "type": "array", + "description": "An optional array of strings representing the names of package presets to inherit from. The preset will inherit all of the fields from the inherits presets by default (except name, hidden, inherits, description, and displayName), but can override them as desired. If multiple inherits presets provide conflicting values for the same field, the earlier preset in the inherits list will be preferred. Presets in CMakePresets.json must not inherit from presets in CMakeUserPresets.json.", + "items": { + "type": "string", + "description": "An optional string representing the name of the preset to inherit from.", + "minLength": 1 + } + } + ] + }, + "configurePreset": { + "type": "string", + "description": "An optional string specifying the name of a configure preset to associate with this package preset. If configurePreset is not specified, it must be inherited from the inherits preset (unless this preset is hidden). The build tree directory is inferred from the configure preset.", + "minLength": 1 + }, + "vendor": { + "type": "object", + "description": "An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the root-level vendor field. If vendors use their own per-preset vendor field, they should implement inheritance in a sensible manner when appropriate.", + "properties": {} + }, + "displayName": { + "type": "string", + "description": "An optional string with a human-friendly name of the preset." + }, + "description": { + "type": "string", + "description": "An optional string with a human-friendly description of the preset." + }, + "inheritConfigureEnvironment": { + "type": "boolean", + "description": "An optional boolean that defaults to true. If true, the environment variables from the associated configure preset are inherited after all inherited package preset environments, but before environment variables explicitly specified in this package preset." + }, + "environment": { + "type": "object", + "description": "An optional map of environment variables. The key is the variable name (which must not be an empty string). Each variable is set regardless of whether or not a value was given to it by the process's environment. This field supports macro expansion, and environment variables in this map may reference each other, and may be listed in any order, as long as such references do not cause a cycle (for example,if ENV_1 is $env{ENV_2}, ENV_2 may not be $env{ENV_1}.) Environment variables are inherited through the inherits field, and the preset's environment will be the union of its own environment and the environment from all its parents. If multiple presets in this union define the same variable, the standard rules of inherits are applied. Setting a variable to null causes it to not be set, even if a value was inherited from another preset.", + "properties": {}, + "additionalProperties": { + "anyOf": [ + { + "type": "null", + "description": "Setting a variable to null causes it to not be set, even if a value was inherited from another preset." + }, + { + "type": "string", + "description": "A string representing the value of the variable." + } + ] + }, + "propertyNames": { + "pattern": "^.+$" + } + }, + "condition": { "$ref": "#/definitions/topCondition" }, + "generators": { + "type": "array", + "description": "An optional list of strings representing generators for CPack to use.", + "items": { + "type": "string", + "description": "An optional string representing the name of the CPack generator to use." + } + }, + "configurations": { + "type": "array", + "description": "An optional list of strings representing build configurations for CPack to package.", + "items": { + "type": "string", + "description": "An optional string representing the name of the configuration to use." + } + }, + "variables": { + "type": "object", + "description": "An optional map of variables to pass to CPack, equivalent to -D arguments. Each key is the name of a variable, and the value is the string to assign to that variable.", + "items": { + "type": "string", + "description": "An optional string representing the value of the variable." + } + }, + "configFile": { + "type": "string", + "description": "An optional string representing the config file for CPack to use." + }, + "output": { + "type": "object", + "description": "An optional object specifying output options.", + "properties": { + "debug": { + "type": "boolean", + "description": "An optional boolean specifying whether or not to print debug information. A value of true is equivalent to passing --debug on the command line." + }, + "verbose": { + "type": "boolean", + "description": "An optional boolean specifying whether or not to print verbosely. A value of true is equivalent to passing --verbose on the command line." + } + }, + "additionalProperties": false + }, + "packageName": { + "type": "string", + "description": "An optional string representing the package name." + }, + "packageVersion": { + "type": "string", + "description": "An optional string representing the package version." + }, + "packageDirectory": { + "type": "string", + "description": "An optional string representing the directory in which to place the package." + }, + "vendorName": { + "type": "string", + "description": "An optional string representing the vendor name." + } + }, + "required": [ + "name" + ] + } + }, + "packagePresetsV6": { + "type": "array", + "description": "An optional array of package preset objects. Used to specify arguments to cpack. Available in version 6 and higher.", + "allOf": [ + { "$ref": "#/definitions/packagePresetsItemsV6" } + ], + "items": { + "type": "object", + "properties": { + "name": {}, + "hidden": {}, + "inherits": {}, + "configurePreset": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "inheritConfigureEnvironment": {}, + "environment": {}, + "condition": {}, + "generators": {}, + "configurations": {}, + "variables": {}, + "configFile": {}, + "output": {}, + "packageName": {}, + "packageVersion": {}, + "packageDirectory": {}, + "vendorName": {} + }, + "required": [ + "name" + ], + "additionalProperties": false + } + }, + "workflowPresetsItemsV6": { + "type": "array", + "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order. Available in version 6 and higher.", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "A required string representing the machine-friendly name of the preset. This identifier is used in the --preset argument. There must not be two presets (configure, build, test, package, or workflow) in the union of CMakePresets.json and CMakeUserPresets.json in the same directory with the same name.", + "minLength": 1 + }, + "vendor": { + "type": "object", + "description": "An optional map containing vendor-specific information. CMake does not interpret the contents of this field except to verify that it is a map if it does exist. However, it should follow the same conventions as the root-level vendor field.", + "properties": {} + }, + "displayName": { + "type": "string", + "description": "An optional string with a human-friendly name of the preset." + }, + "description": { + "type": "string", + "description": "An optional string with a human-friendly description of the preset." + }, + "steps": { + "type": "array", + "description": "A required array of objects describing the steps of the workflow. The first step must be a configure preset, and all subsequent steps must be non-configure presets whose configurePreset field matches the starting configure preset.", + "items": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "A required string. The first step must be configure. Subsequent steps must be either build, test, or package.", + "enum": ["configure", "build", "test", "package"] + }, + "name": { + "type": "string", + "description": "A required string representing the name of the configure, build, test, or package preset to run as this workflow step.", + "minLength": 1 + } + }, + "required": [ + "type", + "name" + ], + "additionalProperties": false + } + } + }, + "required": [ + "name", + "steps" + ], + "additionalProperties": false + } + }, + "workflowPresetsV6": { + "type": "array", + "description": "An optional array of workflow preset objects. Used to execute configure, build, test, and package presets in order. Available in version 6 and higher.", + "allOf": [ + { "$ref": "#/definitions/workflowPresetsItemsV6" } + ], + "items": { + "type": "object", + "properties": { + "name": {}, + "vendor": {}, + "displayName": {}, + "description": {}, + "steps": {} + }, + "required": [ + "name", + "steps" + ], + "additionalProperties": false + } + }, "condition": { "anyOf": [ { diff --git a/Help/module/FindOpenSP.rst b/Help/module/FindOpenSP.rst new file mode 100644 index 0000000..1a3da01 --- /dev/null +++ b/Help/module/FindOpenSP.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindOpenSP.cmake diff --git a/Help/module/FindSDL_gfx.rst b/Help/module/FindSDL_gfx.rst new file mode 100644 index 0000000..e05d661 --- /dev/null +++ b/Help/module/FindSDL_gfx.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/FindSDL_gfx.cmake diff --git a/Help/policy/CMP0058.rst b/Help/policy/CMP0058.rst index 06cc74b..a9a8f1c 100644 --- a/Help/policy/CMP0058.rst +++ b/Help/policy/CMP0058.rst @@ -71,6 +71,9 @@ every custom command dependency, even on source files, needs to be treated this way because CMake does not have enough information to know which files are generated as byproducts of custom commands. +Introducing Byproducts +^^^^^^^^^^^^^^^^^^^^^^ + CMake 3.2 introduced the ``BYPRODUCTS`` option to the :command:`add_custom_command` and :command:`add_custom_target` commands. This option allows byproducts to be specified explicitly: diff --git a/Help/policy/CMP0140.rst b/Help/policy/CMP0140.rst new file mode 100644 index 0000000..dea8989 --- /dev/null +++ b/Help/policy/CMP0140.rst @@ -0,0 +1,17 @@ +CMP0140 +------- + +.. versionadded:: 3.25 + +The :command:`return` command checks its parameters. + +The ``OLD`` behavior for this policy is to ignore any parameters given to the +command. +The ``NEW`` behavior is to check the validity of the parameters. + +This policy was introduced in CMake version 3.25. +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/policy/CMP0141.rst b/Help/policy/CMP0141.rst new file mode 100644 index 0000000..970e41d --- /dev/null +++ b/Help/policy/CMP0141.rst @@ -0,0 +1,55 @@ +CMP0141 +------- + +.. versionadded:: 3.25 + +MSVC debug information format flags are selected by an abstraction. + +Compilers targeting the MSVC ABI have flags to select the debug information +format. Debug information format selection typically varies with build +configuration. + +In CMake 3.24 and below, debug information format flags are added to +the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` cache entries by CMake +automatically. This allows users to edit their cache entries to adjust the +flags. However, the presence of such default flags is problematic for +projects that want to choose a different runtime library programmatically. +In particular, it requires string editing of the +:variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` variables with knowledge of the +CMake builtin defaults so they can be replaced. + +CMake 3.25 and above prefer to leave the debug information format flags +out of the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` values and instead +offer a first-class abstraction. The +:variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` variable and +:prop_tgt:`MSVC_DEBUG_INFORMATION_FORMAT` target property may be set to +select the MSVC debug information format. If they are not set, CMake +enables debug information in debug configurations using the default value +``$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>``, if supported by the +compiler, and otherwise ``$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>``. + +This policy provides compatibility with projects that have not been updated +to be aware of the abstraction. The policy setting takes effect as of the +first :command:`project` or :command:`enable_language` command that enables +a language whose compiler targets the MSVC ABI. + +.. note:: + + Once the policy has taken effect at the top of a project, that choice + will be used throughout the tree. In projects that have nested projects + in subdirectories, be sure to confirm if everything is working with the + selected policy behavior. + +The ``OLD`` behavior for this policy is to place MSVC debug information +format flags in the default :variable:`CMAKE_<LANG>_FLAGS_<CONFIG>` cache +entries and ignore the :variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` +abstraction. The ``NEW`` behavior for this policy is to *not* place MSVC +debug information format flags in the default cache entries and use +the abstraction instead. + +This policy was introduced in CMake version 3.25. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn +when this policy is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/policy/CMP0142.rst b/Help/policy/CMP0142.rst new file mode 100644 index 0000000..1f928f0 --- /dev/null +++ b/Help/policy/CMP0142.rst @@ -0,0 +1,27 @@ +CMP0142 +------- + +.. versionadded:: 3.25 + +The :generator:`Xcode` generator does not append per-config suffixes to +library search paths. + +In CMake 3.24 and below, the :generator:`Xcode` generator preceded each +entry of a library search path with a copy of itself appended with +``$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)``. This was left from +very early versions of CMake in which per-config directories were not well +modeled. Such paths often do not exist, resulting in warnings from the +toolchain. CMake 3.25 and above prefer to not add such library search +paths. This policy provides compatibility for projects that may have been +accidentally relying on the old behavior. + +The ``OLD`` behavior for this policy is to append +``$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)`` to all library search paths. +The ``NEW`` behavior is to not modify library search paths. + +This policy was introduced in CMake version 3.25. Use the +:command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly. +Unlike many policies, CMake version |release| does *not* warn +when this policy is not set and simply uses ``OLD`` behavior. + +.. include:: DEPRECATED.txt diff --git a/Help/prop_dir/SYSTEM.rst b/Help/prop_dir/SYSTEM.rst new file mode 100644 index 0000000..4f923b7 --- /dev/null +++ b/Help/prop_dir/SYSTEM.rst @@ -0,0 +1,10 @@ +SYSTEM +------ + +.. versionadded:: 3.25 + +This directory property is used to initialize the :prop_tgt:`SYSTEM` +target property for targets created in that directory. It is set to +true by :command:`add_subdirectory` and +:command:`FetchContent_Declare` when the ``SYSTEM`` option is given +as an argument to those commands. diff --git a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst index d93a9c1..a31ee3a 100644 --- a/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst +++ b/Help/prop_gbl/CMAKE_CUDA_KNOWN_FEATURES.rst @@ -36,4 +36,9 @@ The features known to this version of CMake are: Compiler mode is at least CUDA/C++ 23. +``cuda_std_26`` + .. versionadded:: 3.25 + + Compiler mode is at least CUDA/C++ 26. + .. include:: CMAKE_LANG_STD_FLAGS.txt diff --git a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst index 6846850..3832f1a 100644 --- a/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst +++ b/Help/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.rst @@ -46,6 +46,11 @@ but it does not necessarily imply complete conformance to that standard. Compiler mode is at least C++ 23. +``cxx_std_26`` + .. versionadded:: 3.25 + + Compiler mode is at least C++ 26. + .. include:: CMAKE_LANG_STD_FLAGS.txt Low level individual compile features diff --git a/Help/prop_inst/CPACK_START_MENU_SHORTCUTS.rst b/Help/prop_inst/CPACK_START_MENU_SHORTCUTS.rst index fb8807f..e70eeb4 100644 --- a/Help/prop_inst/CPACK_START_MENU_SHORTCUTS.rst +++ b/Help/prop_inst/CPACK_START_MENU_SHORTCUTS.rst @@ -3,7 +3,7 @@ CPACK_START_MENU_SHORTCUTS .. versionadded:: 3.3 -Species a list of shortcut names that should be created in the `Start Menu` +Species a list of shortcut names that should be created in the ``Start Menu`` for this file. The property is currently only supported by the :cpack_gen:`CPack WIX Generator`. diff --git a/Help/prop_test/FIXTURES_REQUIRED.rst b/Help/prop_test/FIXTURES_REQUIRED.rst index f850830..7a05601 100644 --- a/Help/prop_test/FIXTURES_REQUIRED.rst +++ b/Help/prop_test/FIXTURES_REQUIRED.rst @@ -19,10 +19,11 @@ be executed. The cleanup tests for the fixture will always be executed, even if some setup tests fail. When CTest is asked to execute only a subset of tests (e.g. by the use of -regular expressions or when run with the ``--rerun-failed`` command line -option), it will automatically add any setup or cleanup tests for fixtures -required by any of the tests that are in the execution set. This behavior can -be overridden with the ``-FS``, ``-FC`` and ``-FA`` command line options to +regular expressions or when run with the :option:`--rerun-failed <ctest --rerun-failed>` +command line option), it will automatically add any setup or cleanup tests for +fixtures required by any of the tests that are in the execution set. This +behavior can be overridden with the :option:`-FS <ctest -FS>`, +:option:`-FC <ctest -FC>` and :option:`-FA <ctest -FA>` command line options to :manual:`ctest(1)` if desired. Since setup and cleanup tasks are also tests, they can have an ordering diff --git a/Help/prop_test/LABELS.rst b/Help/prop_test/LABELS.rst index a06f152..d827adc 100644 --- a/Help/prop_test/LABELS.rst +++ b/Help/prop_test/LABELS.rst @@ -4,7 +4,7 @@ LABELS Specify a list of text labels associated with a test. The labels are reported in both the ``ctest`` output summary and in dashboard submissions. They can also be used to filter the set of tests to be executed (see the -``ctest -L`` and ``ctest -LE`` :ref:`CTest Options`). +:option:`ctest -L` and :option:`ctest -LE` options). See :ref:`Additional Labels` for adding labels to a test dynamically during test execution. diff --git a/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst b/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst index 19323cb..0d2b295 100644 --- a/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst +++ b/Help/prop_tgt/COMPILE_WARNING_AS_ERROR.rst @@ -5,8 +5,8 @@ COMPILE_WARNING_AS_ERROR Specify whether to treat warnings on compile as errors. If enabled, adds a flag to treat warnings on compile as errors. -If the ``--compile-no-warning-as-error`` option is given on the -:manual:`cmake(1)` command line, this property is ignored. +If the :option:`cmake --compile-no-warning-as-error` option is given +on the :manual:`cmake(1)` command line, this property is ignored. This property is not implemented for all compilers. It is silently ignored if there is no implementation for the compiler being used. The currently @@ -26,10 +26,12 @@ implemented :variable:`compiler IDs <CMAKE_<LANG>_COMPILER_ID>` are: * ``NVIDIA`` (CUDA) * ``QCC`` * ``SunPro`` +* ``Tasking`` * ``TI`` * ``VisualAge`` * ``XL`` * ``XLClang`` This property is initialized by the value of the variable -:variable:`CMAKE_COMPILE_WARNING_AS_ERROR` if it is set when a target is created. +:variable:`CMAKE_COMPILE_WARNING_AS_ERROR` if it is set when a target is +created. diff --git a/Help/prop_tgt/CUDA_STANDARD.rst b/Help/prop_tgt/CUDA_STANDARD.rst index 950ba12..ada69b9 100644 --- a/Help/prop_tgt/CUDA_STANDARD.rst +++ b/Help/prop_tgt/CUDA_STANDARD.rst @@ -39,6 +39,12 @@ Supported values are: CUDA C++23 +``26`` + .. versionadded:: 3.25 + + CUDA C++26. CMake 3.25 and later *recognize* ``26`` as a valid value, + no version has support for any compiler. + If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This means that using: diff --git a/Help/prop_tgt/CXX_MODULE_DIRS.rst b/Help/prop_tgt/CXX_MODULE_DIRS.rst new file mode 100644 index 0000000..a32b5b1 --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_DIRS.rst @@ -0,0 +1,19 @@ +CXX_MODULE_DIRS +--------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Semicolon-separated list of base directories of the target's default +C++ module set (i.e. the file set with name and type ``CXX_MODULES``). The +property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +This property is normally only set by :command:`target_sources(FILE_SET)` +rather than being manipulated directly. + +See :prop_tgt:`CXX_MODULE_DIRS_<NAME>` for the list of base directories in +other C++ module sets. diff --git a/Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst b/Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst new file mode 100644 index 0000000..9190991 --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_DIRS_NAME.rst @@ -0,0 +1,19 @@ +CXX_MODULE_DIRS_<NAME> +---------------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Semicolon-separated list of base directories of the target's ``<NAME>`` C++ +module set, which has the set type ``CXX_MODULES``. The property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +This property is normally only set by :command:`target_sources(FILE_SET)` +rather than being manipulated directly. + +See :prop_tgt:`CXX_MODULE_DIRS` for the list of base directories in the +default C++ module set. See :prop_tgt:`CXX_MODULE_SETS` for the file set names +of all C++ module sets. diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst new file mode 100644 index 0000000..5f33111 --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS.rst @@ -0,0 +1,19 @@ +CXX_MODULE_HEADER_UNIT_DIRS +--------------------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Semicolon-separated list of base directories of the target's default C++ +module header set (i.e. the file set with name and type +``CXX_MODULE_HEADER_UNITS``). The property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +This property is normally only set by :command:`target_sources(FILE_SET)` +rather than being manipulated directly. + +See :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS_<NAME>` for the list of base +directories in other C++ module header sets. diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst new file mode 100644 index 0000000..b6163da --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_DIRS_NAME.rst @@ -0,0 +1,21 @@ +CXX_MODULE_HEADER_UNIT_DIRS_<NAME> +---------------------------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Semicolon-separated list of base directories of the target's ``<NAME>`` C++ +module header set, which has the set type ``CXX_MODULE_HEADER_UNITS``. The +property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +This property is normally only set by :command:`target_sources(FILE_SET)` +rather than being manipulated directly. + +See :prop_tgt:`CXX_MODULE_HEADER_UNIT_DIRS` for the list of base directories +in the default C++ module header set. See +:prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS` for the file set names of all C++ +module header sets. diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst new file mode 100644 index 0000000..3b1bd04 --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET.rst @@ -0,0 +1,20 @@ +CXX_MODULE_HEADER_UNIT_SET +-------------------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Semicolon-separated list of files in the target's default C++ module header +set, (i.e. the file set with name and type ``CXX_MODULE_HEADER_UNITS``). If +any of the paths are relative, they are computed relative to the target's +source directory. The property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +This property is normally only set by :command:`target_sources(FILE_SET)` +rather than being manipulated directly. + +See :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET_<NAME>` for the list of files in +other C++ module header sets. diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst new file mode 100644 index 0000000..ffc2daf --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SETS.rst @@ -0,0 +1,20 @@ +CXX_MODULE_HEADER_UNIT_SETS +--------------------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` C++ module header +sets (i.e. all file sets with the type ``CXX_MODULE_HEADER_UNITS``). Files +listed in these file sets are treated as source files for the purpose of IDE +integration. + +C++ module header sets may be defined using the :command:`target_sources` +command ``FILE_SET`` option with type ``CXX_MODULE_HEADER_UNITS``. + +See also :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET_<NAME>`, +:prop_tgt:`CXX_MODULE_HEADER_UNIT_SET` and +:prop_tgt:`INTERFACE_CXX_MODULE_HEADER_UNIT_SETS`. diff --git a/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst new file mode 100644 index 0000000..4bf5069 --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_HEADER_UNIT_SET_NAME.rst @@ -0,0 +1,21 @@ +CXX_MODULE_HEADER_UNIT_SET_<NAME> +--------------------------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Semicolon-separated list of files in the target's ``<NAME>`` C++ module header +set, which has the set type ``CXX_MODULE_HEADER_UNITS``. If any of the paths +are relative, they are computed relative to the target's source directory. The +property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +This property is normally only set by :command:`target_sources(FILE_SET)` +rather than being manipulated directly. + +See :prop_tgt:`CXX_MODULE_HEADER_UNIT_SET` for the list of files in the +default C++ module header set. See :prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS` for +the file set names of all C++ module header sets. diff --git a/Help/prop_tgt/CXX_MODULE_SET.rst b/Help/prop_tgt/CXX_MODULE_SET.rst new file mode 100644 index 0000000..f5cd8b2 --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_SET.rst @@ -0,0 +1,20 @@ +CXX_MODULE_SET +-------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Semicolon-separated list of files in the target's default C++ module set, +(i.e. the file set with name and type ``CXX_MODULES``). If any of the paths +are relative, they are computed relative to the target's source directory. The +property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +This property is normally only set by :command:`target_sources(FILE_SET)` +rather than being manipulated directly. + +See :prop_tgt:`CXX_MODULE_SET_<NAME>` for the list of files in other C++ +module sets. diff --git a/Help/prop_tgt/CXX_MODULE_SETS.rst b/Help/prop_tgt/CXX_MODULE_SETS.rst new file mode 100644 index 0000000..0e8945a --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_SETS.rst @@ -0,0 +1,18 @@ +CXX_MODULE_SETS +--------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` C++ module sets (i.e. +all file sets with the type ``CXX_MODULES``). Files listed in these file sets +are treated as source files for the purpose of IDE integration. + +C++ module sets may be defined using the :command:`target_sources` command +``FILE_SET`` option with type ``CXX_MODULES``. + +See also :prop_tgt:`CXX_MODULE_SET_<NAME>`, :prop_tgt:`CXX_MODULE_SET` and +:prop_tgt:`INTERFACE_CXX_MODULE_SETS`. diff --git a/Help/prop_tgt/CXX_MODULE_SET_NAME.rst b/Help/prop_tgt/CXX_MODULE_SET_NAME.rst new file mode 100644 index 0000000..5674c99 --- /dev/null +++ b/Help/prop_tgt/CXX_MODULE_SET_NAME.rst @@ -0,0 +1,20 @@ +CXX_MODULE_SET_<NAME> +--------------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Semicolon-separated list of files in the target's ``<NAME>`` C++ module set, +which has the set type ``CXX_MODULES``. If any of the paths are relative, they +are computed relative to the target's source directory. The property supports +:manual:`generator expressions <cmake-generator-expressions(7)>`. + +This property is normally only set by :command:`target_sources(FILE_SET)` +rather than being manipulated directly. + +See :prop_tgt:`CXX_MODULE_SET` for the list of files in the default C++ module +set. See :prop_tgt:`CXX_MODULE_SETS` for the file set names of all C++ module +sets. diff --git a/Help/prop_tgt/CXX_STANDARD.rst b/Help/prop_tgt/CXX_STANDARD.rst index b10d201..9b381e4 100644 --- a/Help/prop_tgt/CXX_STANDARD.rst +++ b/Help/prop_tgt/CXX_STANDARD.rst @@ -37,6 +37,12 @@ Supported values are: C++23 +``26`` + .. versionadded:: 3.25 + + C++26. CMake 3.25 and later *recognize* ``26`` as a valid value, + no version has support for any compiler. + If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This means that using: diff --git a/Help/prop_tgt/EXPORT_NO_SYSTEM.rst b/Help/prop_tgt/EXPORT_NO_SYSTEM.rst new file mode 100644 index 0000000..61f0a8d --- /dev/null +++ b/Help/prop_tgt/EXPORT_NO_SYSTEM.rst @@ -0,0 +1,11 @@ +EXPORT_NO_SYSTEM +---------------- + +.. versionadded:: 3.25 + +Specifies that :command:`install(EXPORT)` and :command:`export` commands will +generate an imported target with :prop_tgt:`SYSTEM` property `OFF`. + +See the :prop_tgt:`NO_SYSTEM_FROM_IMPORTED` target property to set this +behavior on the target *consuming* the include directories rather than the +one *providing* them. diff --git a/Help/prop_tgt/HIP_STANDARD.rst b/Help/prop_tgt/HIP_STANDARD.rst index 0c767c6..9de8730 100644 --- a/Help/prop_tgt/HIP_STANDARD.rst +++ b/Help/prop_tgt/HIP_STANDARD.rst @@ -25,6 +25,12 @@ Supported values are: ``23`` HIP C++23 +``26`` + .. versionadded:: 3.25 + + HIP C++26. CMake 3.25 and later *recognize* ``26`` as a valid value, + no version has support for any compiler. + If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This means that using: diff --git a/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst b/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst index ee22d6f..913d9f2 100644 --- a/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst +++ b/Help/prop_tgt/IMPORTED_NO_SYSTEM.rst @@ -3,11 +3,21 @@ IMPORTED_NO_SYSTEM .. versionadded:: 3.23 +.. deprecated:: 3.25 + + ``IMPORTED_NO_SYSTEM`` is deprecated. Set :prop_tgt:`SYSTEM` to `OFF` + instead if you don't want target's include directories to be ``SYSTEM`` + when compiling consumers. Set :prop_tgt:`EXPORT_NO_SYSTEM` to `ON` instead + if you don't want the include directories of the imported target generated + by :command:`install(EXPORT)` and :command:`export` commands to be + ``SYSTEM`` when compiling consumers. + Specifies that an :ref:`Imported Target <Imported Targets>` is not a ``SYSTEM`` library. This has the following effects: * Entries of :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` are not treated - as ``SYSTEM`` include directories when compiling consumers, as they + as ``SYSTEM`` include directories when compiling consumers (regardless of + the value of the consumed target's :prop_tgt:`SYSTEM` property), as they would be by default. Entries of :prop_tgt:`INTERFACE_SYSTEM_INCLUDE_DIRECTORIES` are not affected, and will always be treated as ``SYSTEM`` include directories. diff --git a/Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst b/Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst new file mode 100644 index 0000000..3fe6d9a --- /dev/null +++ b/Help/prop_tgt/INTERFACE_CXX_MODULE_HEADER_UNIT_SETS.rst @@ -0,0 +1,18 @@ +INTERFACE_CXX_MODULE_HEADER_UNIT_SETS +------------------------------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Read-only list of the target's ``PUBLIC`` C++ module header sets (i.e. all +file sets with the type ``CXX_MODULE_HEADER_UNITS``). Files listed in these +C++ module header sets can be installed with :command:`install(TARGETS)` and +exported with :command:`install(EXPORT)` and :command:`export`. + +C++ module header sets may be defined using the :command:`target_sources` +command ``FILE_SET`` option with type ``CXX_MODULE_HEADER_UNITS``. + +See also :prop_tgt:`CXX_MODULE_HEADER_UNIT_SETS`. diff --git a/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst b/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst new file mode 100644 index 0000000..c7ed46d --- /dev/null +++ b/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst @@ -0,0 +1,18 @@ +INTERFACE_CXX_MODULE_SETS +------------------------- + +.. versionadded:: 3.25 + +.. note :: + + Experimental. Gated by ``CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API`` + +Read-only list of the target's ``PUBLIC`` C++ module sets (i.e. all file sets +with the type ``CXX_MODULES``). Files listed in these C++ module sets can be +installed with :command:`install(TARGETS)` and exported with +:command:`install(EXPORT)` and :command:`export`. + +C++ module sets may be defined using the :command:`target_sources` command +``FILE_SET`` option with type ``CXX_MODULES``. + +See also :prop_tgt:`CXX_MODULE_SETS`. diff --git a/Help/prop_tgt/LANG_CLANG_TIDY.rst b/Help/prop_tgt/LANG_CLANG_TIDY.rst index af16d3c..31f1876 100644 --- a/Help/prop_tgt/LANG_CLANG_TIDY.rst +++ b/Help/prop_tgt/LANG_CLANG_TIDY.rst @@ -3,13 +3,25 @@ .. versionadded:: 3.6 -This property is implemented only when ``<LANG>`` is ``C``, ``CXX``, ``OBJC`` or ``OBJCXX``. +This property is implemented only when ``<LANG>`` is ``C``, ``CXX``, ``OBJC`` +or ``OBJCXX``. -Specify a :ref:`semicolon-separated list <CMake Language Lists>` containing a command -line for the ``clang-tidy`` tool. The :ref:`Makefile Generators` +Specify a :ref:`semicolon-separated list <CMake Language Lists>` containing +a command line for the ``clang-tidy`` tool. The :ref:`Makefile Generators` and the :generator:`Ninja` generator will run this tool along with the compiler and report a warning if the tool reports any problems. +The specified ``clang-tidy`` command line will be invoked with additional +arguments specifying the source file and, after ``--``, the full compiler +command line. + +.. versionchanged:: 3.25 + + If the specified ``clang-tidy`` command line includes the ``-p`` option, + it will be invoked without ``--`` and the full compiler command line. + ``clang-tidy`` will look up the source file in the specified compiler + commands database. + This property is initialized by the value of the :variable:`CMAKE_<LANG>_CLANG_TIDY` variable if it is set when a target is created. diff --git a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst index cba8ac9..2e039bd 100644 --- a/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst +++ b/Help/prop_tgt/LANG_COMPILER_LAUNCHER.rst @@ -14,3 +14,8 @@ its arguments to the tool. Some example tools are distcc and ccache. This property is initialized by the value of the :variable:`CMAKE_<LANG>_COMPILER_LAUNCHER` variable if it is set when a target is created. + +.. versionadded:: 3.25 + + The property value may use + :manual:`generator expressions <cmake-generator-expressions(7)>`. diff --git a/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt new file mode 100644 index 0000000..889d97a --- /dev/null +++ b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt @@ -0,0 +1,15 @@ +``Embedded`` + Compile with ``-Z7`` or equivalent flag(s) to produce object files + with full symbolic debugging information. +``ProgramDatabase`` + Compile with ``-Zi`` or equivalent flag(s) to produce a program + database that contains all the symbolic debugging information. +``EditAndContinue`` + Compile with ``-ZI`` or equivalent flag(s) to produce a program + database that supports the Edit and Continue feature. + +The value is ignored on non-MSVC compilers, but an unsupported value will +be rejected as an error when using a compiler targeting the MSVC ABI. + +The value may also be the empty string (``""``), in which case no debug +information format flag will be added explicitly by CMake. diff --git a/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT.rst b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT.rst new file mode 100644 index 0000000..0c7845c --- /dev/null +++ b/Help/prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT.rst @@ -0,0 +1,33 @@ +MSVC_DEBUG_INFORMATION_FORMAT +----------------------------- + +.. versionadded:: 3.25 + +Select debug information format when targeting the MSVC ABI. + +The allowed values are: + +.. include:: MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt + +Use :manual:`generator expressions <cmake-generator-expressions(7)>` to +support per-configuration specification. For example, the code: + +.. code-block:: cmake + + add_executable(foo foo.c) + set_property(TARGET foo PROPERTY + MSVC_DEBUG_INFORMATION_FORMAT "$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>") + +selects for the target ``foo`` the program database debug information format +for the Debug configuration. + +If this property is not set, CMake selects a debug information format using +the default value ``$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>``, if +supported by the compiler, and otherwise +``$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>``. + +.. note:: + + This property has effect only when policy :policy:`CMP0141` is set to ``NEW`` + prior to the first :command:`project` or :command:`enable_language` command + that enables a language using a compiler targeting the MSVC ABI. diff --git a/Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst b/Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst index 9b978b2..9f13d38 100644 --- a/Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst +++ b/Help/prop_tgt/MSVC_RUNTIME_LIBRARY.rst @@ -21,7 +21,9 @@ support per-configuration specification. For example, the code: selects for the target ``foo`` a multi-threaded statically-linked runtime library with or without debug information depending on the configuration. -If this property is not set then CMake uses the default value +The property is initialized from the value of the +:variable:`CMAKE_MSVC_RUNTIME_LIBRARY` variable, if it is set. +If the property is not set, then CMake uses the default value ``MultiThreaded$<$<CONFIG:Debug>:Debug>DLL`` to select a MSVC runtime library. .. note:: diff --git a/Help/prop_tgt/OBJCXX_STANDARD.rst b/Help/prop_tgt/OBJCXX_STANDARD.rst index 654e687..6ac8216 100644 --- a/Help/prop_tgt/OBJCXX_STANDARD.rst +++ b/Help/prop_tgt/OBJCXX_STANDARD.rst @@ -31,6 +31,12 @@ Supported values are: Objective C++23 +``26`` + .. versionadded:: 3.25 + + Objective C++26. CMake 3.25 and later *recognize* ``26`` as a valid value, + no version has support for any compiler. + If the value requested does not result in a compile flag being added for the compiler in use, a previous standard flag will be added instead. This means that using: diff --git a/Help/prop_tgt/SYSTEM.rst b/Help/prop_tgt/SYSTEM.rst new file mode 100644 index 0000000..a267738 --- /dev/null +++ b/Help/prop_tgt/SYSTEM.rst @@ -0,0 +1,22 @@ +SYSTEM +------ + +.. versionadded:: 3.25 + +Specifies that a target is a ``SYSTEM`` library. This has the following +effects: + +* Entries of :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` are treated as + ``SYSTEM`` include directories when compiling consumers. + Entries of :prop_tgt:`INTERFACE_SYSTEM_INCLUDE_DIRECTORIES` are not + affected, and will always be treated as ``SYSTEM`` include directories. + +For imported targets, this property defaults to true, which means +that their :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` are treated +as ``SYSTEM`` by default. If their ``SYSTEM`` property is false, +then their :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` will not be +treated as ``SYSTEM``, regardless of the value of the +:prop_tgt:`IMPORTED_NO_SYSTEM` property. + +This target property is initialized from the :prop_dir:`SYSTEM` +directory property when the target is created. diff --git a/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst b/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst index 58476d6..1e84c00 100644 --- a/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst +++ b/Help/prop_tgt/VS_DEBUGGER_COMMAND.rst @@ -9,5 +9,5 @@ The property value may use This is defined in ``<LocalDebuggerCommand>`` in the Visual Studio project file. -This property only works for Visual Studio 2010 and above; +This property only works for Visual Studio 11 2012 and above; it is ignored on other generators. diff --git a/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst b/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst index 6c26601..e54e140 100644 --- a/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst +++ b/Help/prop_tgt/VS_DEBUGGER_COMMAND_ARGUMENTS.rst @@ -9,5 +9,5 @@ The property value may use This is defined in ``<LocalDebuggerCommandArguments>`` in the Visual Studio project file. -This property only works for Visual Studio 2010 and above; +This property only works for Visual Studio 11 2012 and above; it is ignored on other generators. diff --git a/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst b/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst index 2f59a82..60bc2f0 100644 --- a/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst +++ b/Help/prop_tgt/VS_DEBUGGER_ENVIRONMENT.rst @@ -9,5 +9,5 @@ The property value may use This is defined in ``<LocalDebuggerEnvironment>`` in the Visual Studio project file. -This property only works for Visual Studio 2010 and above; +This property only works for Visual Studio 11 2012 and above; it is ignored on other generators. diff --git a/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst b/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst index c163abf..f9ce7aa 100644 --- a/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst +++ b/Help/prop_tgt/VS_DEBUGGER_WORKING_DIRECTORY.rst @@ -9,5 +9,5 @@ The property value may use This is defined in ``<LocalDebuggerWorkingDirectory>`` in the Visual Studio project file. -This property only works for Visual Studio 2010 and above; +This property only works for Visual Studio 11 2012 and above; it is ignored on other generators. diff --git a/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst b/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst index 5212293..8a85ba4 100644 --- a/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst +++ b/Help/prop_tgt/VS_DOTNET_STARTUP_OBJECT.rst @@ -12,7 +12,7 @@ If the property is unset, Visual Studio uses the first matching than one ``Main()`` method is available in the current project, the property becomes mandatory for building the project. -This property only works for Visual Studio 2010 and above; +This property only works for Visual Studio 11 2012 and above; it is ignored on other generators. .. code-block:: cmake diff --git a/Help/prop_tgt/VS_KEYWORD.rst b/Help/prop_tgt/VS_KEYWORD.rst index 6c2e042..221b986 100644 --- a/Help/prop_tgt/VS_KEYWORD.rst +++ b/Help/prop_tgt/VS_KEYWORD.rst @@ -7,4 +7,4 @@ Can be set to change the visual studio keyword, for example Qt integration works better if this is set to Qt4VSv1.0. Use the :prop_tgt:`VS_GLOBAL_KEYWORD` target property to set the -keyword for Visual Studio 10 (2010) and newer. +keyword for Visual Studio 11 (2012) and newer. diff --git a/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst b/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst index 8f46d2f..fa3c5bc 100644 --- a/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst +++ b/Help/prop_tgt/XCODE_GENERATE_SCHEME.rst @@ -30,6 +30,9 @@ at target creation time. - :prop_tgt:`XCODE_SCHEME_THREAD_SANITIZER_STOP` - :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER` - :prop_tgt:`XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP` +- :prop_tgt:`XCODE_SCHEME_LAUNCH_CONFIGURATION` +- :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_API_VALIDATION` +- :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION` - :prop_tgt:`XCODE_SCHEME_ZOMBIE_OBJECTS` The following target properties will be applied on the @@ -41,4 +44,5 @@ The following target properties will be applied on the - :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE` - :prop_tgt:`XCODE_SCHEME_ENVIRONMENT` - :prop_tgt:`XCODE_SCHEME_EXECUTABLE` +- :prop_tgt:`XCODE_SCHEME_LAUNCH_MODE` - :prop_tgt:`XCODE_SCHEME_WORKING_DIRECTORY` diff --git a/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst b/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst new file mode 100644 index 0000000..3b801c5 --- /dev/null +++ b/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst @@ -0,0 +1,14 @@ +XCODE_SCHEME_ENABLE_GPU_API_VALIDATION +-------------------------------------- + +.. versionadded:: 3.25 + +Property value for ``Metal: API Validation`` in the Options section of +the generated Xcode scheme. + +This property is initialized by the value of the variable +:variable:`CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION` +if it is set when a target is created. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst b/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst new file mode 100644 index 0000000..5358087 --- /dev/null +++ b/Help/prop_tgt/XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst @@ -0,0 +1,14 @@ +XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION +----------------------------------------- + +.. versionadded:: 3.25 + +Property value for ``Metal: Shader Validation`` in the Options section of +the generated Xcode scheme. + +This property is initialized by the value of the variable +:variable:`CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION` +if it is set when a target is created. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_LAUNCH_CONFIGURATION.rst b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_CONFIGURATION.rst new file mode 100644 index 0000000..9643322 --- /dev/null +++ b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_CONFIGURATION.rst @@ -0,0 +1,13 @@ +XCODE_SCHEME_LAUNCH_CONFIGURATION +--------------------------------- + +.. versionadded:: 3.25 + +Set the build configuration to run the target. + +This property is initialized by the value of the variable +:variable:`CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION` +if it is set when a target is created. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst new file mode 100644 index 0000000..df5ae07 --- /dev/null +++ b/Help/prop_tgt/XCODE_SCHEME_LAUNCH_MODE.rst @@ -0,0 +1,22 @@ +XCODE_SCHEME_LAUNCH_MODE +------------------------ + +.. versionadded:: 3.25 + +Property value for ``Launch`` in the Info section of the generated Xcode +scheme. + +Possible values are: + +``AUTO`` + Launch automatically. This is the default. + +``WAIT`` + Wait for the executable to be launched. + +This property is initialized by the value of the variable +:variable:`CMAKE_XCODE_SCHEME_LAUNCH_MODE` if it is set when a target is +created. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/release/3.20.rst b/Help/release/3.20.rst index 42e95be..71f47c4 100644 --- a/Help/release/3.20.rst +++ b/Help/release/3.20.rst @@ -217,8 +217,8 @@ Autogen CTest ----- -* :manual:`ctest(1)` gained a ``--test-dir`` option to specify the directory - in which to look for tests. +* :manual:`ctest(1)` gained a :option:`--test-dir <ctest --test-dir>` + option to specify the directory in which to look for tests. CPack ----- diff --git a/Help/release/3.21.rst b/Help/release/3.21.rst index 462d2be..91c3768 100644 --- a/Help/release/3.21.rst +++ b/Help/release/3.21.rst @@ -49,15 +49,15 @@ Languages Command-Line ------------ -* :manual:`cmake(1)` gained the ``--install-prefix <dir>`` +* :manual:`cmake(1)` gained the :option:`--install-prefix <cmake --install-prefix>` command-line option to specify the location of the install prefix. -* :manual:`cmake(1)` gained the ``--toolchain <path/to/file>`` +* :manual:`cmake(1)` gained the :option:`--toolchain <cmake --toolchain>` command-line option to specify a toolchain file. -* :manual:`cmake(1)` ``-E capabilities`` output, for some generators, - may now contain a ``supportedPlatforms`` field listing platforms - known to be supported in :variable:`CMAKE_GENERATOR_PLATFORM`. +* :manual:`cmake(1)` :option:`-E capabilities <cmake-E capabilities>` output, + for some generators, may now contain a ``supportedPlatforms`` field listing + platforms known to be supported in :variable:`CMAKE_GENERATOR_PLATFORM`. * Messages printed to a terminal now may be colored by message type. @@ -208,8 +208,8 @@ CTest :prop_test:`ATTACHED_FILES_ON_FAIL` test properties. See :ref:`Additional Test Measurements` for more information. -* :manual:`ctest(1)` gained a ``--output-junit`` option to write test results - to a JUnit XML file. +* :manual:`ctest(1)` gained a :option:`--output-junit <ctest --output-junit>` + option to write test results to a JUnit XML file. * The :command:`ctest_build` command gained a ``PARALLEL_LEVEL`` option. diff --git a/Help/release/3.23.rst b/Help/release/3.23.rst index 209be45..064616b 100644 --- a/Help/release/3.23.rst +++ b/Help/release/3.23.rst @@ -43,19 +43,22 @@ Generators Command-Line ------------ -* The :manual:`cmake(1)` ``--build`` command, when used with +* The :manual:`cmake(1)` :option:`--build <cmake --build>` command, when used with :ref:`Visual Studio Generators` on projects that set the :prop_tgt:`VS_PACKAGE_REFERENCES` target property, now automatically restores package references from NuGet. The cache variable :variable:`CMAKE_VS_NUGET_PACKAGE_RESTORE` may be set to toggle this behavior - in a build tree. Use the ``--resolve-package-references=<on|off|only>`` + in a build tree. Use the + :option:`--resolve-package-references <cmake--build --resolve-package-references>` command-line option to control the behavior on one invocation. -* The :manual:`cmake(1)` command line tool gained a ``--debug-find-pkg=`` +* The :manual:`cmake(1)` command line tool gained a + :option:`--debug-find-pkg <cmake --debug-find-pkg>` option to enable debug messages under specific :command:`find_package` calls. -* The :manual:`cmake(1)` command line tool gained a ``--debug-find-var=`` +* The :manual:`cmake(1)` command line tool gained a + :option:`--debug-find-var <cmake --debug-find-var>` option to enable debug messages for ``find_*`` calls that use specific result variables. diff --git a/Help/release/3.24.rst b/Help/release/3.24.rst index 3857c5d..1d331d5 100644 --- a/Help/release/3.24.rst +++ b/Help/release/3.24.rst @@ -34,25 +34,28 @@ Generators Command-Line ------------ -* :manual:`cmake(1)` gained the ``--fresh`` command-line option to remove - any existing ``CMakeCache.txt`` file and associated ``CMakeFiles/`` +* :manual:`cmake(1)` gained the :option:`--fresh <cmake --fresh>` command-line + option to remove any existing ``CMakeCache.txt`` file and associated ``CMakeFiles/`` directory, when configuring a build tree, thus starting a new configuration as if the build tree were freshly created. -* :manual:`cmake(1)` gained the ``--compile-no-warning-as-error`` command-line - option which causes the effects of the :prop_tgt:`COMPILE_WARNING_AS_ERROR` - target property and :variable:`CMAKE_COMPILE_WARNING_AS_ERROR` variable - to be ignored. +* :manual:`cmake(1)` gained the + :option:`--compile-no-warning-as-error <cmake --compile-no-warning-as-error>` + command-line option which causes the effects of the + :prop_tgt:`COMPILE_WARNING_AS_ERROR` target property and + :variable:`CMAKE_COMPILE_WARNING_AS_ERROR` variable to be ignored. -* The :manual:`cmake(1)` ``--trace=json-v1`` trace format gained fields - ``global_frame`` and ``line_end``. +* The :manual:`cmake(1)` :option:`--trace=json-v1 <cmake --trace>` trace + format gained fields ``global_frame`` and ``line_end``. -* The :manual:`cmake(1)` ``-E`` commands ``cat`` and ``env`` learned to respect - a double dash (``--``) argument that acts as a delimiter indicating the end of - options. Any following arguments are treated as operands/positional arguments, - even if they begin with a dash ``-`` character. +* The :manual:`cmake(1)` :option:`-E <cmake -E>` commands :option:`cat <cmake-E cat>` + and :option:`env <cmake-E env>` learned to respect a double dash + (:option:`-- <cmake-E_env -->`) argument that acts as a delimiter indicating + the end of options. Any following arguments are treated as operands/positional + arguments, even if they begin with a dash ``-`` character. -* The :manual:`cmake(1)` ``-E tar`` command gained the ``--touch`` option +* The :manual:`cmake(1)` :option:`-E tar <cmake-E tar>` command gained the + :option:`--touch <cmake-E_tar --touch>` option to keep the current local timestamp instead of extracting file timestamps from the archive. @@ -289,9 +292,10 @@ Generator Expressions CTest ----- -* :manual:`ctest(1)` gained a ``--test-output-truncation`` option (and - corresponding :variable:`CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION` variable) to - specify the truncation mode once the maximum test output size has been +* :manual:`ctest(1)` gained a + :option:`--test-output-truncation <ctest --test-output-truncation>` option + (and corresponding :variable:`CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION` variable) + to specify the truncation mode once the maximum test output size has been reached. Possible values are ``tail`` (default), ``middle`` or ``head``. CPack diff --git a/Help/release/3.25.rst b/Help/release/3.25.rst new file mode 100644 index 0000000..c119fae --- /dev/null +++ b/Help/release/3.25.rst @@ -0,0 +1,240 @@ +CMake 3.25 Release Notes +************************ + +.. only:: html + + .. contents:: + +Changes made since CMake 3.24 include the following. + +New Features +============ + +Presets +------- + +* The :manual:`cmake-presets(7)` schema version has been bumped to ``6``. + +* The :manual:`cmake-presets(7)` format now supports a + ``packagePresets`` field to specify presets for :option:`cpack --preset`. + +* The :manual:`cmake-presets(7)` format now supports a + ``workflowPresets`` field to specify presets for :option:`cmake --workflow`. + +* The :manual:`cmake-presets(7)` format now supports a + ``outputJUnitFile`` field to specify JUnit output in test presets. + +Languages +--------- + +* The :manual:`Compile Features <cmake-compile-features(7)>` functionality + is now aware of C++26, and defines a ``cxx_std_26`` meta-feature. + C++26 compiler modes may also be specified via the :prop_tgt:`CXX_STANDARD`, + :prop_tgt:`CUDA_STANDARD`, :prop_tgt:`HIP_STANDARD`, + or :prop_tgt:`OBJCXX_STANDARD` target properties. + +* ``CUDA`` language support now includes device link-time optimization when + using ``nvcc``. The :variable:`CMAKE_INTERPROCEDURAL_OPTIMIZATION` variable + and the associated :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target property + will activate device LTO. + +Command-Line +------------ + +* A :option:`cmake --workflow --preset <cmake--workflow --preset>` mode was + added to drive sequences of configure, build, test, and package operations + through a single command. + +* The :option:`cmake -E capabilities <cmake-E capabilities>` command + gained a new ``tls`` field that tells whether or not TLS is enabled. + +* The :option:`cmake -E env <cmake-E env>` command-line tool gained + a ``--modify`` flag to support :prop_test:`ENVIRONMENT_MODIFICATION` + operations. + +* The :option:`cmake --debug-trycompile` option now prints log messages + reporting the directory in which each try-compile check is done. + +Compilers +--------- + +* Support for the `Tasking compiler toolsets`_ (SmartCode, TriCore, + Standalone: ARM, MCS, 8051) was added with compiler id ``Tasking``. + See the :variable:`CMAKE_TASKING_TOOLSET` variable. + +.. _`Tasking compiler toolsets`: https://tasking.com + +Commands +-------- + +* The :command:`add_subdirectory` command gained a ``SYSTEM`` option + to enable the :prop_dir:`SYSTEM` directory property in the subdirectory. + +* The :command:`block` and :command:`endblock` commands were added to manage + specific scopes (policy or variable) for a contained block of commands. + +* The :command:`cmake_language` command gained a new + ``GET_MESSAGE_LOG_LEVEL`` sub-command. It can be used to + query the current message logging level. + +* The :command:`find_file`, :command:`find_path`, :command:`find_library`, and + :command:`find_program` commands gained a ``VALIDATOR`` option to specify a + function to be called for each candidate item to validate it. + +* The :command:`find_package` command now considers paths of + the form ``<prefix>/<name>*/(cmake|CMake)/<name>*/`` when + searching for package configuration files. + +* The :command:`return` command gained a ``PROPAGATE`` option to propagate + variables to the scope to which control returns. + See policy :policy:`CMP0140`. + +* The :command:`try_compile` and :command:`try_run` commands gained new + signatures that more consistently use keyword dispatch and do not require a + binary directory to be specified. Additionally, these signatures use a + unique directory for each invocation, which allows multiple outputs to be + preserved when using :option:`cmake --debug-trycompile`. + +* The :command:`try_compile` and :command:`try_run` commands gained the + option ``NO_CACHE`` to store results in normal variables. + +* The :command:`try_run` command gained ``RUN_OUTPUT_STDOUT_VARIABLE`` + and ``RUN_OUTPUT_STDERR_VARIABLE`` options to capture stdout and stderr + separately from the output of the compiled program. + +Variables +--------- + +* The :variable:`BSD` and :variable:`CMAKE_HOST_BSD` variables are now set + to a string value when the target or host system is BSD, respectively. + +* The :variable:`LINUX` and :variable:`CMAKE_HOST_LINUX` variables are + now set to true when the target or host system is Linux, respectively. + +* The :variable:`CMAKE_MSVC_DEBUG_INFORMATION_FORMAT` variable and + :prop_tgt:`MSVC_DEBUG_INFORMATION_FORMAT` target property were introduced + to select the debug information format for compilers targeting the MSVC ABI. + See policy :policy:`CMP0141`. + +* The :variable:`CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION` variable and + corresponding :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_API_VALIDATION` target + property were added to tell the :generator:`Xcode` generator what to put + in the scheme's ``Metal: API Validation`` setting. + +* The :variable:`CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION` variable and + corresponding :prop_tgt:`XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION` target + property were added to tell the :generator:`Xcode` generator what to put + in the scheme's ``Metal: Shader Validation`` setting. + +* The :variable:`CMAKE_XCODE_SCHEME_LAUNCH_MODE` variable and corresponding + :prop_tgt:`XCODE_SCHEME_LAUNCH_MODE` target property were added to tell + the :generator:`Xcode` generator what to put in the scheme's "Launch" + mode setting. + +* The :variable:`CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION` variable and + corresponding :prop_tgt:`XCODE_SCHEME_LAUNCH_CONFIGURATION` target + property were added to tell the :generator:`Xcode` generator what + configuration to put in the scheme's Launch action. + +Properties +---------- + +* The :prop_tgt:`<LANG>_COMPILER_LAUNCHER` target property now supports + :manual:`generator expressions <cmake-generator-expressions(7)>`. + +* The :prop_tgt:`EXPORT_NO_SYSTEM` target property was added to + specify that :command:`install(EXPORT)` and :command:`export` + commands will generate na imported target with + :prop_tgt:`SYSTEM` property ``OFF``. + +* The :prop_tgt:`SYSTEM` target property was added to specify + whether a target should be treated as a system library (i.e. + its include directories are automatically ``SYSTEM`` when + compiling consumers). If not set, the default is the previous + behavior: on for imported targets and off for other targets. + +* The :prop_dir:`SYSTEM` directory property was added to initialize the + :prop_tgt:`SYSTEM` target property for targets created in that directory. + +Modules +------- + +* The :module:`FetchContent` module :command:`FetchContent_Declare` + command gained a ``SYSTEM`` option to enable the :prop_dir:`SYSTEM` + directory property in the subdirectory. + +* The :module:`FindCUDAToolkit` module now provides a target for + :ref:`nvtx3 <cuda_toolkit_nvtx3>` for CUDA 10.0+, which supersedes + :ref:`nvToolsExt <cuda_toolkit_nvToolsExt>`. A deprecation warning + is emitted when using ``nvToolsExt`` if the project requires CMake + 3.25 and CUDA 10.0+ is used. + +* The :module:`FindDoxygen` module's version handling has been improved: + + * Multiple candidate installations will now be considered, if needed, + to satisfy version constraints. Previously, only the first one + encountered would be considered. + + * Version ranges are supported. + + * Variations in the version format reported by Doxygen are now + tolerated (e.g. a trailing git commit hash). + +* The :module:`FindOpenAL` module now provides an imported target. + +* The :module:`FindOpenSP` module was added to find the OpenSP library. + +* The :module:`FindVulkan` module gained support for new components: + + ``dxc`` + DirectX Shader Compiler. + + ``volk`` + Volk open-source vulkan meta-loader. + +CPack +----- + +* The :cpack_gen:`CPack Archive Generator` gained a new + :variable:`CPACK_ARCHIVE_FILE_EXTENSION` variable to control + the package file name extension. + +* The :cpack_gen:`CPack NSIS Generator` gained two new variables + :variable:`CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS` and + :variable:`CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS` + to provide arguments to the nsis executable invocation. + +* The :module:`CPack` module gained the :variable:`CPACK_READELF_EXECUTABLE`, + :variable:`CPACK_OBJCOPY_EXECUTABLE`, and + :variable:`CPACK_OBJDUMP_EXECUTABLE` variables to control the locations + of binutils used by :manual:`cpack(1)`. + +Deprecated and Removed Features +=============================== + +* The :prop_tgt:`IMPORTED_NO_SYSTEM` target property has been deprecated + in favor of :prop_tgt:`SYSTEM` and :prop_tgt:`EXPORT_NO_SYSTEM`. + +* The :generator:`Visual Studio 10 2010` generator has been removed. + +* The :generator:`Visual Studio 11 2012` generator is now deprecated + and will be removed in a future version of CMake. + +Other Changes +============= + +* On Windows, when targeting the MSVC ABI, the :command:`find_library` command + now accepts ``.a`` file names after first considering ``.lib``. This is + symmetric with existing behavior when targeting the GNU ABI, in which the + command accepts ``.lib`` file names after first considering ``.a``. + +* The :envvar:`SSL_CERT_FILE` and :envvar:`SSL_CERT_DIR` environment + variables can now be used to override where to find certificate + authorities for TLS/SSL operations. + +* If :prop_tgt:`<LANG>_CLANG_TIDY` includes a ``-p`` argument, the + full compiler command line is no longer appended after ``--``. + +* The :generator:`Xcode` generator no longer adds the per-config suffix + ``$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)`` to library search paths. + See policy :policy:`CMP0142`. diff --git a/Help/release/index.rst b/Help/release/index.rst index 4dfac8a..b6ecf7b 100644 --- a/Help/release/index.rst +++ b/Help/release/index.rst @@ -13,6 +13,7 @@ Releases .. toctree:: :maxdepth: 1 + 3.25 <3.25> 3.24 <3.24> 3.23 <3.23> 3.22 <3.22> diff --git a/Help/variable/BSD.rst b/Help/variable/BSD.rst new file mode 100644 index 0000000..fdfe5ec --- /dev/null +++ b/Help/variable/BSD.rst @@ -0,0 +1,7 @@ +BSD +--- + +.. versionadded:: 3.25 + +Set to a string value when the target system is BSD. This value can be one of +the following: DragonFlyBSD, FreeBSD, OpenBSD, or NetBSD. diff --git a/Help/variable/CMAKE_ANDROID_API.rst b/Help/variable/CMAKE_ANDROID_API.rst index 4388bf2..aba9b6e 100644 --- a/Help/variable/CMAKE_ANDROID_API.rst +++ b/Help/variable/CMAKE_ANDROID_API.rst @@ -8,6 +8,7 @@ Edition`, this variable may be set to specify the default value for the :prop_tgt:`ANDROID_API` target property. See that target property for additional information. -Otherwise, when :ref:`Cross Compiling for Android`, this variable provides -the Android API version number targeted. This will be the same value as -the :variable:`CMAKE_SYSTEM_VERSION` variable for ``Android`` platforms. +When :ref:`Cross Compiling for Android`, the :variable:`CMAKE_SYSTEM_VERSION` +variable represents the Android API version number targeted. For historical +reasons, if a toolchain file sets ``CMAKE_ANDROID_API``, but not +``CMAKE_SYSTEM_VERSION``, the latter will be initialized using the former. diff --git a/Help/variable/CMAKE_BINARY_DIR.rst b/Help/variable/CMAKE_BINARY_DIR.rst index 3b323b7..e601eb8 100644 --- a/Help/variable/CMAKE_BINARY_DIR.rst +++ b/Help/variable/CMAKE_BINARY_DIR.rst @@ -7,7 +7,7 @@ This is the full path to the top level of the current CMake build tree. For an in-source build, this would be the same as :variable:`CMAKE_SOURCE_DIR`. -When run in -P script mode, CMake sets the variables +When run in :option:`cmake -P` script mode, CMake sets the variables :variable:`CMAKE_BINARY_DIR`, :variable:`CMAKE_SOURCE_DIR`, :variable:`CMAKE_CURRENT_BINARY_DIR` and :variable:`CMAKE_CURRENT_SOURCE_DIR` to the current working directory. diff --git a/Help/variable/CMAKE_CFG_INTDIR.rst b/Help/variable/CMAKE_CFG_INTDIR.rst index 43668ea..3a57659 100644 --- a/Help/variable/CMAKE_CFG_INTDIR.rst +++ b/Help/variable/CMAKE_CFG_INTDIR.rst @@ -19,7 +19,7 @@ Example values: :: $(ConfigurationName) = Visual Studio 9 - $(Configuration) = Visual Studio 10 + $(Configuration) = Visual Studio 11 and above $(CONFIGURATION) = Xcode . = Make-based tools . = Ninja diff --git a/Help/variable/CMAKE_COMMAND.rst b/Help/variable/CMAKE_COMMAND.rst index f80b46c..e65ff8c 100644 --- a/Help/variable/CMAKE_COMMAND.rst +++ b/Help/variable/CMAKE_COMMAND.rst @@ -4,5 +4,5 @@ CMAKE_COMMAND The full path to the :manual:`cmake(1)` executable. This is the full path to the CMake executable :manual:`cmake(1)` which is -useful from custom commands that want to use the ``cmake -E`` option for +useful from custom commands that want to use the :option:`cmake -E` option for portable system commands. (e.g. ``/usr/local/bin/cmake``) diff --git a/Help/variable/CMAKE_CPACK_COMMAND.rst b/Help/variable/CMAKE_CPACK_COMMAND.rst index 3a81d68..f851a18 100644 --- a/Help/variable/CMAKE_CPACK_COMMAND.rst +++ b/Help/variable/CMAKE_CPACK_COMMAND.rst @@ -5,6 +5,6 @@ CMAKE_CPACK_COMMAND Full path to :manual:`cpack(1)` command installed with CMake. -This is the full path to the CPack executable :manual:`cpack(1)` which is -useful from custom commands that want to use the :manual:`cmake(1)` ``-E`` -option for portable system commands. +This is the full path to the CPack executable :manual:`cpack(1)` +that can be used for custom commands or tests to invoke +CPack commands. diff --git a/Help/variable/CMAKE_CTEST_COMMAND.rst b/Help/variable/CMAKE_CTEST_COMMAND.rst index b2942e2..a3b751f 100644 --- a/Help/variable/CMAKE_CTEST_COMMAND.rst +++ b/Help/variable/CMAKE_CTEST_COMMAND.rst @@ -3,6 +3,6 @@ CMAKE_CTEST_COMMAND Full path to :manual:`ctest(1)` command installed with CMake. -This is the full path to the CTest executable :manual:`ctest(1)` which is -useful from custom commands that want to use the :manual:`cmake(1)` ``-E`` -option for portable system commands. +This is the full path to the CTest executable :manual:`ctest(1)` +that can be used for custom commands or tests to invoke +CTest commands. diff --git a/Help/variable/CMAKE_CURRENT_BINARY_DIR.rst b/Help/variable/CMAKE_CURRENT_BINARY_DIR.rst index 8fc85ee..15f81d2 100644 --- a/Help/variable/CMAKE_CURRENT_BINARY_DIR.rst +++ b/Help/variable/CMAKE_CURRENT_BINARY_DIR.rst @@ -9,7 +9,7 @@ create a binary directory in the build tree, and as it is being processed this variable will be set. For in-source builds this is the current source directory being processed. -When run in -P script mode, CMake sets the variables +When run in :option:`cmake -P` script mode, CMake sets the variables :variable:`CMAKE_BINARY_DIR`, :variable:`CMAKE_SOURCE_DIR`, :variable:`CMAKE_CURRENT_BINARY_DIR` and :variable:`CMAKE_CURRENT_SOURCE_DIR` to the current working directory. diff --git a/Help/variable/CMAKE_CURRENT_SOURCE_DIR.rst b/Help/variable/CMAKE_CURRENT_SOURCE_DIR.rst index 1a25efc..5b86026 100644 --- a/Help/variable/CMAKE_CURRENT_SOURCE_DIR.rst +++ b/Help/variable/CMAKE_CURRENT_SOURCE_DIR.rst @@ -6,7 +6,7 @@ The path to the source directory currently being processed. This is the full path to the source directory that is currently being processed by cmake. -When run in -P script mode, CMake sets the variables +When run in :option:`cmake -P` script mode, CMake sets the variables :variable:`CMAKE_BINARY_DIR`, :variable:`CMAKE_SOURCE_DIR`, :variable:`CMAKE_CURRENT_BINARY_DIR` and :variable:`CMAKE_CURRENT_SOURCE_DIR` to the current working directory. diff --git a/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst b/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst index f77e939..58818f4 100644 --- a/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst +++ b/Help/variable/CMAKE_DISABLE_FIND_PACKAGE_PackageName.rst @@ -13,6 +13,6 @@ This switch should be used during the initial CMake run. Otherwise if the package has already been found in a previous CMake run, the variables which have been stored in the cache will still be there. In that case it is recommended to remove the cache variables for this -package from the cache using the cache editor or :manual:`cmake(1)` ``-U`` +package from the cache using the cache editor or :option:`cmake -U`. See also the :variable:`CMAKE_REQUIRE_FIND_PACKAGE_<PackageName>` variable. diff --git a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst index 53a19dc..a7e9029 100644 --- a/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst +++ b/Help/variable/CMAKE_EXPORT_COMPILE_COMMANDS.rst @@ -33,7 +33,7 @@ property for all targets. .. note:: This option is implemented only by :ref:`Makefile Generators` - and the :generator:`Ninja`. It is ignored on other generators. + and :ref:`Ninja Generators`. It is ignored on other generators. This option currently does not work well in combination with the :prop_tgt:`UNITY_BUILD` target property or the diff --git a/Help/variable/CMAKE_FIND_DEBUG_MODE.rst b/Help/variable/CMAKE_FIND_DEBUG_MODE.rst index 8f2a82f..48b0dce 100644 --- a/Help/variable/CMAKE_FIND_DEBUG_MODE.rst +++ b/Help/variable/CMAKE_FIND_DEBUG_MODE.rst @@ -13,7 +13,7 @@ error: * :command:`find_package` Output is designed for human consumption and not for parsing. -Enabling this variable is equivalent to using :manual:`cmake <cmake(1)>` ``--debug-find`` +Enabling this variable is equivalent to using :option:`cmake --debug-find` with the added ability to enable debugging for a subset of find calls. .. code-block:: cmake diff --git a/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst b/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst index 5d45fb0..b27a3d9 100644 --- a/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst +++ b/Help/variable/CMAKE_FIND_PACKAGE_REDIRECTS_DIR.rst @@ -25,4 +25,4 @@ CMake configures the project. ``CMAKE_FIND_PACKAGE_REDIRECTS_DIR`` is only set in CMake project mode. It is not set when CMake is run in script mode -(i.e. :manual:`cmake -P ... <cmake(1)>`). +(i.e. :option:`cmake -P`). diff --git a/Help/variable/CMAKE_GENERATOR.rst b/Help/variable/CMAKE_GENERATOR.rst index ec52cd4..0e249eb 100644 --- a/Help/variable/CMAKE_GENERATOR.rst +++ b/Help/variable/CMAKE_GENERATOR.rst @@ -7,6 +7,6 @@ The name of the generator that is being used to generate the build files. (e.g. ``Unix Makefiles``, ``Ninja``, etc.) The value of this variable should never be modified by project code. -A generator may be selected via the :manual:`cmake(1)` ``-G`` option, +A generator may be selected via the :option:`cmake -G` option, interactively in :manual:`cmake-gui(1)`, or via the :envvar:`CMAKE_GENERATOR` environment variable. diff --git a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst index b17d83a..acb7b2e 100644 --- a/Help/variable/CMAKE_GENERATOR_PLATFORM.rst +++ b/Help/variable/CMAKE_GENERATOR_PLATFORM.rst @@ -7,7 +7,7 @@ Generator-specific target platform specification provided by user. Some CMake generators support a target platform name to be given to the native build system to choose a compiler toolchain. -If the user specifies a platform name (e.g. via the :manual:`cmake(1)` ``-A`` +If the user specifies a platform name (e.g. via the :option:`cmake -A` option or via the :envvar:`CMAKE_GENERATOR_PLATFORM` environment variable) the value will be available in this variable. diff --git a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst index 45f2d32..4855477 100644 --- a/Help/variable/CMAKE_GENERATOR_TOOLSET.rst +++ b/Help/variable/CMAKE_GENERATOR_TOOLSET.rst @@ -5,7 +5,7 @@ Native build system toolset specification provided by user. Some CMake generators support a toolset specification to tell the native build system how to choose a compiler. If the user specifies -a toolset (e.g. via the :manual:`cmake(1)` ``-T`` option or via +a toolset (e.g. via the :option:`cmake -T` option or via the :envvar:`CMAKE_GENERATOR_TOOLSET` environment variable) the value will be available in this variable. diff --git a/Help/variable/CMAKE_HOST_BSD.rst b/Help/variable/CMAKE_HOST_BSD.rst new file mode 100644 index 0000000..d3554f9 --- /dev/null +++ b/Help/variable/CMAKE_HOST_BSD.rst @@ -0,0 +1,7 @@ +CMAKE_HOST_BSD +-------------- + +.. versionadded:: 3.25 + +Set to a string value when the host system is BSD. This value can be one of +the following: DragonFlyBSD, FreeBSD, OpenBSD, or NetBSD. diff --git a/Help/variable/CMAKE_HOST_LINUX.rst b/Help/variable/CMAKE_HOST_LINUX.rst new file mode 100644 index 0000000..e2361bd --- /dev/null +++ b/Help/variable/CMAKE_HOST_LINUX.rst @@ -0,0 +1,6 @@ +CMAKE_HOST_LINUX +---------------- + +.. versionadded:: 3.25 + +Set to true when the host system is Linux. diff --git a/Help/variable/CMAKE_INSTALL_PREFIX.rst b/Help/variable/CMAKE_INSTALL_PREFIX.rst index 6d42ea8..c76727e 100644 --- a/Help/variable/CMAKE_INSTALL_PREFIX.rst +++ b/Help/variable/CMAKE_INSTALL_PREFIX.rst @@ -27,8 +27,9 @@ first :command:`project` invocation. The ``CMAKE_INSTALL_PREFIX`` may be defined when configuring a build tree to set its installation prefix. Or, when using the :manual:`cmake(1)` -command-line tool's ``--install`` mode, one may specify a different prefix -using the ``--prefix`` option: +command-line tool's :option:`--install <cmake --install>` mode, one may specify +a different prefix using the :option:`--prefix <cmake--install --prefix>` +option: .. code-block:: shell diff --git a/Help/variable/CMAKE_LANG_COMPILER.rst b/Help/variable/CMAKE_LANG_COMPILER.rst index e694b33..db8f4e1 100644 --- a/Help/variable/CMAKE_LANG_COMPILER.rst +++ b/Help/variable/CMAKE_LANG_COMPILER.rst @@ -14,7 +14,8 @@ This variable can be set by the user during the first time a build tree is confi If a non-full path value is supplied then CMake will resolve the full path of the compiler. -The variable could be set in a user supplied toolchain file or via `-D` on the command line. +The variable could be set in a user supplied toolchain file or via +:option:`-D <cmake -D>` on the command line. .. note:: Options that are required to make the compiler work correctly can be included diff --git a/Help/variable/CMAKE_LANG_COMPILER_ID.rst b/Help/variable/CMAKE_LANG_COMPILER_ID.rst index 6a0a1d9..0174c56 100644 --- a/Help/variable/CMAKE_LANG_COMPILER_ID.rst +++ b/Help/variable/CMAKE_LANG_COMPILER_ID.rst @@ -6,43 +6,62 @@ Compiler identification string. A short string unique to the compiler vendor. Possible values include: -:: - - Absoft = Absoft Fortran (absoft.com) - ADSP = Analog VisualDSP++ (analog.com) - AppleClang = Apple Clang (apple.com) - ARMCC = ARM Compiler (arm.com) - ARMClang = ARM Compiler based on Clang (arm.com) - Bruce = Bruce C Compiler - CCur = Concurrent Fortran (ccur.com) - Clang = LLVM Clang (clang.llvm.org) - Cray = Cray Compiler (cray.com) - Embarcadero, Borland = Embarcadero (embarcadero.com) - Flang = Classic Flang Fortran Compiler (https://github.com/flang-compiler/flang) - LLVMFlang = LLVM Flang Fortran Compiler (https://github.com/llvm/llvm-project/tree/main/flang) - Fujitsu = Fujitsu HPC compiler (Trad mode) - FujitsuClang = Fujitsu HPC compiler (Clang mode) - G95 = G95 Fortran (g95.org) - GNU = GNU Compiler Collection (gcc.gnu.org) - GHS = Green Hills Software (www.ghs.com) - HP = Hewlett-Packard Compiler (hp.com) - IAR = IAR Systems (iar.com) - Intel = Intel Compiler (intel.com) - IntelLLVM = Intel LLVM-Based Compiler (intel.com) - LCC = MCST Elbrus C/C++/Fortran Compiler (mcst.ru) - MSVC = Microsoft Visual Studio (microsoft.com) - NVHPC = NVIDIA HPC SDK Compiler (nvidia.com) - NVIDIA = NVIDIA CUDA Compiler (nvidia.com) - OpenWatcom = Open Watcom (openwatcom.org) - PGI = The Portland Group (pgroup.com) - PathScale = PathScale (pathscale.com) - SDCC = Small Device C Compiler (sdcc.sourceforge.net) - SunPro = Oracle Solaris Studio (oracle.com) - TI = Texas Instruments (ti.com) - TinyCC = Tiny C Compiler (tinycc.org) - XL, VisualAge, zOS = IBM XL (ibm.com) - XLClang = IBM Clang-based XL (ibm.com) - IBMClang = IBM LLVM-based Compiler (ibm.com) +=============================== =============================================== +Value Name +=============================== =============================================== +``Absoft`` `Absoft Fortran`_ +``ADSP`` Analog VisualDSP++ +``AppleClang`` Apple Clang +``ARMCC`` ARM Compiler +``ARMClang`` ARM Compiler based on Clang +``Bruce`` Bruce C Compiler +``CCur`` Concurrent Fortran +``Clang`` `LLVM Clang`_ +``Cray`` Cray Compiler +``Embarcadero``, ``Borland`` `Embarcadero`_ +``Flang`` `Classic Flang Fortran Compiler`_ +``LLVMFlang`` `LLVM Flang Fortran Compiler`_ +``Fujitsu`` Fujitsu HPC compiler (Trad mode) +``FujitsuClang`` Fujitsu HPC compiler (Clang mode) +``G95`` `G95 Fortran`_ +``GNU`` `GNU Compiler Collection`_ +``GHS`` `Green Hills Software`_ +``HP`` Hewlett-Packard Compiler +``IAR`` IAR Systems +``Intel`` Intel Compiler +``IntelLLVM`` Intel LLVM-Based Compiler +``LCC`` MCST Elbrus C/C++/Fortran Compiler +``MSVC`` `Microsoft Visual Studio`_ +``NVHPC`` `NVIDIA HPC Compiler`_ +``NVIDIA`` `NVIDIA CUDA Compiler`_ +``OpenWatcom`` `Open Watcom`_ +``PGI`` The Portland Group +``PathScale`` PathScale +``SDCC`` `Small Device C Compiler`_ +``SunPro`` Oracle Solaris Studio +``Tasking`` `Tasking Compiler Toolsets`_ +``TI`` Texas Instruments +``TinyCC`` `Tiny C Compiler`_ +``XL``, ``VisualAge``, ``zOS`` IBM XL +``XLClang`` IBM Clang-based XL +``IBMClang`` IBM LLVM-based Compiler +=============================== =============================================== This variable is not guaranteed to be defined for all compilers or languages. + +.. _Absoft Fortran: https://www.absoft.com +.. _LLVM Clang: https://clang.llvm.org +.. _Embarcadero: https://www.embarcadero.com +.. _Classic Flang Fortran Compiler: https://github.com/flang-compiler/flang +.. _LLVM Flang Fortran Compiler: https://github.com/llvm/llvm-project/tree/main/flang +.. _G95 Fortran: http://g95.sourceforge.net +.. _GNU Compiler Collection: https://gcc.gnu.org +.. _Green Hills Software: https://www.ghs.com/products/compiler.html +.. _Microsoft Visual Studio: https://visualstudio.microsoft.com +.. _NVIDIA HPC Compiler: https://developer.nvidia.com/hpc-compilers +.. _NVIDIA CUDA Compiler: https://developer.nvidia.com/cuda-llvm-compiler +.. _Open Watcom: https://open-watcom.github.io +.. _Small Device C Compiler: http://sdcc.sourceforge.net +.. _Tiny C Compiler: https://bellard.org/tcc +.. _Tasking Compiler Toolsets: https://tasking.com diff --git a/Help/variable/CMAKE_LANG_FLAGS.rst b/Help/variable/CMAKE_LANG_FLAGS.rst index 2784397..4b39b1d 100644 --- a/Help/variable/CMAKE_LANG_FLAGS.rst +++ b/Help/variable/CMAKE_LANG_FLAGS.rst @@ -5,7 +5,9 @@ Flags for all build types. ``<LANG>`` flags used regardless of the value of :variable:`CMAKE_BUILD_TYPE`. -This is initialized for each language from environment variables: +For each language, if this variable is not defined, it is initialized +and stored in the cache using values from environment variables in +combination with CMake's builtin defaults for the toolchain: * ``CMAKE_C_FLAGS``: Initialized by the :envvar:`CFLAGS` environment variable. @@ -15,6 +17,12 @@ This is initialized for each language from environment variables: Initialized by the :envvar:`CUDAFLAGS` environment variable. * ``CMAKE_Fortran_FLAGS``: Initialized by the :envvar:`FFLAGS` environment variable. +* ``CMAKE_CSharp_FLAGS``: + Initialized by the :envvar:`CSFLAGS` environment variable. +* ``CMAKE_HIP_FLAGS``: + Initialized by the :envvar:`HIPFLAGS` environment variable. +* ``CMAKE_ISPC_FLAGS``: + Initialized by the :envvar:`ISPCFLAGS` environment variable. This value is a command-line string fragment. Therefore, multiple options should be separated by spaces, and options with spaces should be quoted. diff --git a/Help/variable/CMAKE_MAKE_PROGRAM.rst b/Help/variable/CMAKE_MAKE_PROGRAM.rst index a3c8b7c..9769c7a 100644 --- a/Help/variable/CMAKE_MAKE_PROGRAM.rst +++ b/Help/variable/CMAKE_MAKE_PROGRAM.rst @@ -59,6 +59,6 @@ to configure the project: variable, changing the value has undefined behavior. The ``CMAKE_MAKE_PROGRAM`` variable is set for use by project code. -The value is also used by the :manual:`cmake(1)` ``--build`` and -:manual:`ctest(1)` ``--build-and-test`` tools to launch the native +The value is also used by the :option:`cmake --build` and +:option:`ctest --build-and-test` tools to launch the native build process. diff --git a/Help/variable/CMAKE_MESSAGE_CONTEXT.rst b/Help/variable/CMAKE_MESSAGE_CONTEXT.rst index 41ace43..7274b7b 100644 --- a/Help/variable/CMAKE_MESSAGE_CONTEXT.rst +++ b/Help/variable/CMAKE_MESSAGE_CONTEXT.rst @@ -3,7 +3,7 @@ CMAKE_MESSAGE_CONTEXT .. versionadded:: 3.17 -When enabled by the :manual:`cmake <cmake(1)>` ``--log-context`` command line +When enabled by the :option:`cmake --log-context` command line option or the :variable:`CMAKE_MESSAGE_CONTEXT_SHOW` variable, the :command:`message` command converts the ``CMAKE_MESSAGE_CONTEXT`` list into a dot-separated string surrounded by square brackets and prepends it to each line diff --git a/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst index 3b45d1d..4539c90 100644 --- a/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst +++ b/Help/variable/CMAKE_MESSAGE_LOG_LEVEL.rst @@ -5,8 +5,9 @@ CMAKE_MESSAGE_LOG_LEVEL When set, this variable specifies the logging level used by the :command:`message` command. Valid values are the same as those for the -``--log-level`` command line option of the :manual:`cmake(1)` program. -If this variable is set and the ``--log-level`` command line option is +:option:`--log-level <cmake --log-level>` command line option of the +:manual:`cmake(1)` program. If this variable is set and the +:option:`--log-level <cmake --log-level>` command line option is given, the command line option takes precedence. The main advantage to using this variable is to make a log level persist @@ -15,3 +16,8 @@ subsequent CMake runs will continue to use the chosen log level. Projects should not set this variable, it is intended for users so that they may control the log level according to their own needs. + +.. versionadded:: 3.25 + See the :command:`cmake_language` + :ref:`cmake_language <query_message_log_level>` command for a way to query + the current message logging level. diff --git a/Help/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.rst b/Help/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.rst new file mode 100644 index 0000000..80df8fc --- /dev/null +++ b/Help/variable/CMAKE_MSVC_DEBUG_INFORMATION_FORMAT.rst @@ -0,0 +1,36 @@ +CMAKE_MSVC_DEBUG_INFORMATION_FORMAT +----------------------------------- + +.. versionadded:: 3.25 + +Select the MSVC debug information format targeting the MSVC ABI. +This variable is used to initialize the +:prop_tgt:`MSVC_DEBUG_INFORMATION_FORMAT` property on all targets as they are +created. It is also propagated by calls to the :command:`try_compile` command +into the test project. + +The allowed values are: + +.. include:: ../prop_tgt/MSVC_DEBUG_INFORMATION_FORMAT-VALUES.txt + +Use :manual:`generator expressions <cmake-generator-expressions(7)>` to +support per-configuration specification. For example, the code: + +.. code-block:: cmake + + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>") + +selects for all following targets the program database debug information format +for the Debug configuration. + +If this variable is not set, the :prop_tgt:`MSVC_DEBUG_INFORMATION_FORMAT` +target property will not be set automatically. If that property is not set, +CMake selects a debug information format using the default value +``$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>``, if supported by the +compiler, and otherwise ``$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>``. + +.. note:: + + This variable has effect only when policy :policy:`CMP0141` is set to ``NEW`` + prior to the first :command:`project` or :command:`enable_language` command + that enables a language using a compiler targeting the MSVC ABI. diff --git a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst index 9dce760..f844105 100644 --- a/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst +++ b/Help/variable/CMAKE_POLICY_WARNING_CMPNNNN.rst @@ -42,5 +42,8 @@ only for the policies that do not warn by default: This variable should not be set by a project in CMake code. Project developers running CMake may set this variable in their cache to enable the warning (e.g. ``-DCMAKE_POLICY_WARNING_CMP<NNNN>=ON``). -Alternatively, running :manual:`cmake(1)` with the ``--debug-output``, -``--trace``, or ``--trace-expand`` option will also enable the warning. +Alternatively, running :manual:`cmake(1)` with the +:option:`--debug-output <cmake --debug-output>`, +:option:`--trace <cmake --trace>`, or +:option:`--trace-expand <cmake --trace-expand>` option will also +enable the warning. diff --git a/Help/variable/CMAKE_SCRIPT_MODE_FILE.rst b/Help/variable/CMAKE_SCRIPT_MODE_FILE.rst index 981af60..313fb4e 100644 --- a/Help/variable/CMAKE_SCRIPT_MODE_FILE.rst +++ b/Help/variable/CMAKE_SCRIPT_MODE_FILE.rst @@ -1,9 +1,9 @@ CMAKE_SCRIPT_MODE_FILE ---------------------- -Full path to the :manual:`cmake(1)` ``-P`` script file currently being +Full path to the :option:`cmake -P` script file currently being processed. -When run in :manual:`cmake(1)` ``-P`` script mode, CMake sets this variable to +When run in :option:`cmake -P` script mode, CMake sets this variable to the full path of the script file. When run to configure a ``CMakeLists.txt`` file, this variable is not set. diff --git a/Help/variable/CMAKE_SOURCE_DIR.rst b/Help/variable/CMAKE_SOURCE_DIR.rst index d1f1798..7210f75 100644 --- a/Help/variable/CMAKE_SOURCE_DIR.rst +++ b/Help/variable/CMAKE_SOURCE_DIR.rst @@ -7,7 +7,7 @@ This is the full path to the top level of the current CMake source tree. For an in-source build, this would be the same as :variable:`CMAKE_BINARY_DIR`. -When run in ``-P`` script mode, CMake sets the variables +When run in :option:`cmake -P` script mode, CMake sets the variables :variable:`CMAKE_BINARY_DIR`, :variable:`CMAKE_SOURCE_DIR`, :variable:`CMAKE_CURRENT_BINARY_DIR` and :variable:`CMAKE_CURRENT_SOURCE_DIR` to the current working directory. diff --git a/Help/variable/CMAKE_TASKING_TOOLSET.rst b/Help/variable/CMAKE_TASKING_TOOLSET.rst new file mode 100644 index 0000000..940606b --- /dev/null +++ b/Help/variable/CMAKE_TASKING_TOOLSET.rst @@ -0,0 +1,31 @@ +CMAKE_TASKING_TOOLSET +--------------------- + +.. versionadded:: 3.25 + +Select the Tasking toolset which provides the compiler + +Architecture compilers are provided by different toolchains with +incompatible versioning schemes. Set this variable in a +:variable:`toolchain file <CMAKE_TOOLCHAIN_FILE>` so CMake can detect +the compiler and version correctly. If no toolset is specified, +``Standalone`` is assumed. + +Projects that can be built with different architectures and/or toolsets must +take :variable:`CMAKE_TASKING_TOOLSET` and +:variable:`CMAKE_<LANG>_COMPILER_ARCHITECTURE_ID` into account to qualify +:variable:`CMAKE_<LANG>_COMPILER_VERSION`. + +``TriCore`` + Compilers are provided by the TriCore toolset. + +``SmartCode`` + Compilers are provided by the SmartCode toolset. + +``Standalone`` + Compilers are provided by the standalone toolsets. + + .. note:: + + For the TriCore architecture, the compiler from the TriCore toolset is + selected as standalone compiler. diff --git a/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst b/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst index f109a9e..2bb97c4 100644 --- a/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst +++ b/Help/variable/CMAKE_VS_DEVENV_COMMAND.rst @@ -10,5 +10,5 @@ This variable is not defined by other generators even if ``devenv.com`` is installed on the computer. The :variable:`CMAKE_VS_MSBUILD_COMMAND` is also provided for -:generator:`Visual Studio 10 2010` and above. +:generator:`Visual Studio 11 2012` and above. See also the :variable:`CMAKE_MAKE_PROGRAM` variable. diff --git a/Help/variable/CMAKE_VS_MSBUILD_COMMAND.rst b/Help/variable/CMAKE_VS_MSBUILD_COMMAND.rst index 58f2bef..8a521a3 100644 --- a/Help/variable/CMAKE_VS_MSBUILD_COMMAND.rst +++ b/Help/variable/CMAKE_VS_MSBUILD_COMMAND.rst @@ -1,7 +1,7 @@ CMAKE_VS_MSBUILD_COMMAND ------------------------ -The generators for :generator:`Visual Studio 10 2010` and above set this +The generators for :generator:`Visual Studio 11 2012` and above set this variable to the ``MSBuild.exe`` command installed with the corresponding Visual Studio version. diff --git a/Help/variable/CMAKE_WARN_DEPRECATED.rst b/Help/variable/CMAKE_WARN_DEPRECATED.rst index 4a224fa..c7b6159 100644 --- a/Help/variable/CMAKE_WARN_DEPRECATED.rst +++ b/Help/variable/CMAKE_WARN_DEPRECATED.rst @@ -7,4 +7,5 @@ If not ``FALSE``, use of deprecated functionality will issue warnings. If this variable is not set, CMake behaves as if it were set to ``TRUE``. When running :manual:`cmake(1)`, this option can be enabled with the -``-Wdeprecated`` option, or disabled with the ``-Wno-deprecated`` option. +:option:`-Wdeprecated <cmake -Wdeprecated>` option, or disabled with the +:option:`-Wno-deprecated <cmake -Wno-deprecated>` option. diff --git a/Help/variable/CMAKE_XCODE_PLATFORM_TOOLSET.rst b/Help/variable/CMAKE_XCODE_PLATFORM_TOOLSET.rst index 210da52..6d72d14 100644 --- a/Help/variable/CMAKE_XCODE_PLATFORM_TOOLSET.rst +++ b/Help/variable/CMAKE_XCODE_PLATFORM_TOOLSET.rst @@ -5,5 +5,5 @@ Xcode compiler selection. :generator:`Xcode` supports selection of a compiler from one of the installed toolsets. CMake provides the name of the chosen toolset in this -variable, if any is explicitly selected (e.g. via the :manual:`cmake(1)` -``-T`` option). +variable, if any is explicitly selected (e.g. via the :option:`cmake -T` +option). diff --git a/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst b/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst new file mode 100644 index 0000000..ce5c4b3 --- /dev/null +++ b/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION.rst @@ -0,0 +1,13 @@ +CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION +-------------------------------------------- + +.. versionadded:: 3.25 + +Property value for ``Metal: API Validation`` in the Options section of +the generated Xcode scheme. + +This variable initializes the +:prop_tgt:`XCODE_SCHEME_ENABLE_GPU_API_VALIDATION` property on all targets. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst b/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst new file mode 100644 index 0000000..073a6c9 --- /dev/null +++ b/Help/variable/CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION.rst @@ -0,0 +1,13 @@ +CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION +----------------------------------------------- + +.. versionadded:: 3.25 + +Property value for ``Metal: Shader Validation`` in the Options section of +the generated Xcode scheme. + +This variable initializes the +:prop_tgt:`XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION` property on all targets. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION.rst b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION.rst new file mode 100644 index 0000000..e5b4d18 --- /dev/null +++ b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION.rst @@ -0,0 +1,12 @@ +CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION +--------------------------------------- + +.. versionadded:: 3.25 + +Set the build configuration to run the target. + +This variable initializes the :prop_tgt:`XCODE_SCHEME_LAUNCH_CONFIGURATION` +property on all targets. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst new file mode 100644 index 0000000..c15b1ea --- /dev/null +++ b/Help/variable/CMAKE_XCODE_SCHEME_LAUNCH_MODE.rst @@ -0,0 +1,13 @@ +CMAKE_XCODE_SCHEME_LAUNCH_MODE +------------------------------ + +.. versionadded:: 3.25 + +Property value for ``Launch`` in the Info section of the generated Xcode +scheme. + +This variable initializes the :prop_tgt:`XCODE_SCHEME_LAUNCH_MODE` property on +all targets. + +Please refer to the :prop_tgt:`XCODE_GENERATE_SCHEME` target property +documentation to see all Xcode schema related properties. diff --git a/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst index 1c070b8..9bd50db 100644 --- a/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst +++ b/Help/variable/CPACK_CUSTOM_INSTALL_VARIABLES.rst @@ -3,7 +3,7 @@ CPACK_CUSTOM_INSTALL_VARIABLES .. versionadded:: 3.21 -CPack variables (set via e.g. ``cpack -D``, ``CPackConfig.cmake`` or +CPack variables (set via e.g. :option:`cpack -D`, ``CPackConfig.cmake`` or :variable:`CPACK_PROJECT_CONFIG_FILE` scripts) are not directly visible in installation scripts. Instead, one can pass a list of ``varName=value`` pairs in the ``CPACK_CUSTOM_INSTALL_VARIABLES`` variable. At install time, diff --git a/Help/variable/CTEST_CONFIGURATION_TYPE.rst b/Help/variable/CTEST_CONFIGURATION_TYPE.rst index 392845e..932f81d 100644 --- a/Help/variable/CTEST_CONFIGURATION_TYPE.rst +++ b/Help/variable/CTEST_CONFIGURATION_TYPE.rst @@ -6,5 +6,5 @@ CTEST_CONFIGURATION_TYPE Specify the CTest ``DefaultCTestConfigurationType`` setting in a :manual:`ctest(1)` dashboard client script. -If the configuration type is set via ``-C <cfg>`` from the command line +If the configuration type is set via :option:`-C \<cfg\> <ctest -C>` from the command line then this variable is populated accordingly. diff --git a/Help/variable/CTEST_RUN_CURRENT_SCRIPT.rst b/Help/variable/CTEST_RUN_CURRENT_SCRIPT.rst index 32c85ad..8cb6eaa 100644 --- a/Help/variable/CTEST_RUN_CURRENT_SCRIPT.rst +++ b/Help/variable/CTEST_RUN_CURRENT_SCRIPT.rst @@ -4,4 +4,4 @@ CTEST_RUN_CURRENT_SCRIPT .. versionadded:: 3.11 Setting this to 0 prevents :manual:`ctest(1)` from being run again when it -reaches the end of a script run by calling ``ctest -S``. +reaches the end of a script run by calling :option:`ctest -S`. diff --git a/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt b/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt index 8ae6c57..aea1be8 100644 --- a/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt +++ b/Help/variable/LINK_LIBRARY_PREDEFINED_FEATURES.txt @@ -45,8 +45,8 @@ wildcard, and optional parts are shown as ``[...]``): * ``[/path/to/]FwName[.framework]`` - * ``[/path/to/]FwName.framework/FwName`` - * ``[/path/to/]FwName.framework/Versions/*/FwName`` + * ``[/path/to/]FwName.framework/FwName[suffix]`` + * ``[/path/to/]FwName.framework/Versions/*/FwName[suffix]`` Note that CMake recognizes and automatically handles framework targets, even without using the ``$<LINK_LIBRARY:FRAMEWORK,...>`` expression. @@ -59,6 +59,11 @@ ``$<LINK_LIBRARY:FRAMEWORK,...>`` for file paths so that the expected behavior is clear. + .. versionadded:: 3.25 + The :prop_tgt:`FRAMEWORK_MULTI_CONFIG_POSTFIX_<CONFIG>` target property as + well as the ``suffix`` of the framework library name are now supported by + the ``FRAMEWORK`` features. + ``NEEDED_FRAMEWORK`` This is similar to the ``FRAMEWORK`` feature, except it forces the linker to link with the framework even if no symbols are used from it. It uses diff --git a/Help/variable/LINUX.rst b/Help/variable/LINUX.rst new file mode 100644 index 0000000..26379b3 --- /dev/null +++ b/Help/variable/LINUX.rst @@ -0,0 +1,6 @@ +LINUX +----- + +.. versionadded:: 3.25 + +Set to true when the target system is Linux. diff --git a/Modules/CMakeCXXCompilerId.cpp.in b/Modules/CMakeCXXCompilerId.cpp.in index f19bc97..2643326 100644 --- a/Modules/CMakeCXXCompilerId.cpp.in +++ b/Modules/CMakeCXXCompilerId.cpp.in @@ -82,6 +82,7 @@ int main(int argc, char* argv[]) int require = 0; require += info_compiler[argc]; require += info_platform[argc]; + require += info_arch[argc]; #ifdef COMPILER_VERSION_MAJOR require += info_version[argc]; #endif diff --git a/Modules/CMakeCompilerIdDetection.cmake b/Modules/CMakeCompilerIdDetection.cmake index f15974a..75d33e8 100644 --- a/Modules/CMakeCompilerIdDetection.cmake +++ b/Modules/CMakeCompilerIdDetection.cmake @@ -70,6 +70,7 @@ function(compiler_id_detection outvar lang) FujitsuClang Fujitsu GHS + Tasking ) if ("x${lang}" STREQUAL "xC") list(APPEND ordered_compilers diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake index ac0e262..9a3c940 100644 --- a/Modules/CMakeDependentOption.cmake +++ b/Modules/CMakeDependentOption.cmake @@ -84,7 +84,7 @@ macro(CMAKE_DEPENDENT_OPTION option doc default depends force) else() set(${option} "${${option}_ISSET}") endif() - if("x${_CDO_CMP0127}x" STREQUAL "xx" AND "x${depends}x" MATCHES "[^A-Za-z0-9_; ]") + if("x${_CDO_CMP0127}x" STREQUAL "xx" AND "x${depends}x" MATCHES "[^A-Za-z0-9_.; ]") cmake_policy(GET_WARNING CMP0127 _CDO_CMP0127_WARNING) message(AUTHOR_WARNING "${_CDO_CMP0127_WARNING}") endif() diff --git a/Modules/CMakeDetermineCSharpCompiler.cmake b/Modules/CMakeDetermineCSharpCompiler.cmake index da860a8..fe98469 100644 --- a/Modules/CMakeDetermineCSharpCompiler.cmake +++ b/Modules/CMakeDetermineCSharpCompiler.cmake @@ -3,7 +3,7 @@ if(NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])") message(FATAL_ERROR - "C# is currently only supported for Microsoft Visual Studio 2010 and later.") + "C# is currently only supported for Microsoft Visual Studio 11 2012 and later.") endif() include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake) diff --git a/Modules/CMakeDetermineCUDACompiler.cmake b/Modules/CMakeDetermineCUDACompiler.cmake index 0ac06ac..f43b17b 100644 --- a/Modules/CMakeDetermineCUDACompiler.cmake +++ b/Modules/CMakeDetermineCUDACompiler.cmake @@ -275,7 +275,7 @@ if(NOT CMAKE_CUDA_COMPILER_ID_RUN) if(DEFINED CMAKE_CUDA_ARCHITECTURES) if(CMAKE_CUDA_ARCHITECTURES STREQUAL "") message(FATAL_ERROR "CMAKE_CUDA_ARCHITECTURES must be non-empty if set.") - elseif(CMAKE_CUDA_ARCHITECTURES AND NOT CMAKE_CUDA_ARCHITECTURES MATCHES "^([0-9]+(-real|-virtual)?(;[0-9]+(-real|-virtual)?|;)*|all|all-major|native)$") + elseif(CMAKE_CUDA_ARCHITECTURES AND NOT CMAKE_CUDA_ARCHITECTURES MATCHES "^([0-9]+a?(-real|-virtual)?(;[0-9]+a?(-real|-virtual)?|;)*|all|all-major|native)$") message(FATAL_ERROR "CMAKE_CUDA_ARCHITECTURES:\n" " ${CMAKE_CUDA_ARCHITECTURES}\n" @@ -503,7 +503,8 @@ elseif(CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") CMAKE_CUDA_HOST_IMPLICIT_LINK_DIRECTORIES CMAKE_CUDA_HOST_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES log - "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}") + "${CMAKE_CUDA_IMPLICIT_OBJECT_REGEX}" + LANGUAGE CUDA) # Detect CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT from the compiler by looking at which # cudart library exists in the implicit link libraries passed to the host linker. diff --git a/Modules/CMakeDetermineCompileFeatures.cmake b/Modules/CMakeDetermineCompileFeatures.cmake index a08e597..09de7b1 100644 --- a/Modules/CMakeDetermineCompileFeatures.cmake +++ b/Modules/CMakeDetermineCompileFeatures.cmake @@ -63,6 +63,7 @@ function(cmake_determine_compile_features lang) set(CMAKE_CXX17_COMPILE_FEATURES) set(CMAKE_CXX20_COMPILE_FEATURES) set(CMAKE_CXX23_COMPILE_FEATURES) + set(CMAKE_CXX26_COMPILE_FEATURES) include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake") @@ -73,6 +74,9 @@ function(cmake_determine_compile_features lang) return() endif() + if (CMAKE_CXX23_COMPILE_FEATURES AND CMAKE_CXX26_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_CXX26_COMPILE_FEATURES ${CMAKE_CXX23_COMPILE_FEATURES}) + endif() if (CMAKE_CXX20_COMPILE_FEATURES AND CMAKE_CXX23_COMPILE_FEATURES) list(REMOVE_ITEM CMAKE_CXX23_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES}) endif() @@ -97,6 +101,7 @@ function(cmake_determine_compile_features lang) ${CMAKE_CXX17_COMPILE_FEATURES} ${CMAKE_CXX20_COMPILE_FEATURES} ${CMAKE_CXX23_COMPILE_FEATURES} + ${CMAKE_CXX26_COMPILE_FEATURES} ) endif() @@ -107,6 +112,7 @@ function(cmake_determine_compile_features lang) set(CMAKE_CXX17_COMPILE_FEATURES ${CMAKE_CXX17_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_CXX20_COMPILE_FEATURES ${CMAKE_CXX20_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_CXX23_COMPILE_FEATURES ${CMAKE_CXX23_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_CXX26_COMPILE_FEATURES ${CMAKE_CXX26_COMPILE_FEATURES} PARENT_SCOPE) message(CHECK_PASS "done") @@ -119,6 +125,7 @@ function(cmake_determine_compile_features lang) set(CMAKE_CUDA17_COMPILE_FEATURES) set(CMAKE_CUDA20_COMPILE_FEATURES) set(CMAKE_CUDA23_COMPILE_FEATURES) + set(CMAKE_CUDA26_COMPILE_FEATURES) include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake") @@ -129,6 +136,9 @@ function(cmake_determine_compile_features lang) return() endif() + if (CMAKE_CUDA23_COMPILE_FEATURES AND CMAKE_CUDA26_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_CUDA26_COMPILE_FEATURES ${CMAKE_CUDA23_COMPILE_FEATURES}) + endif() if (CMAKE_CUDA20_COMPILE_FEATURES AND CMAKE_CUDA23_COMPILE_FEATURES) list(REMOVE_ITEM CMAKE_CUDA23_COMPILE_FEATURES ${CMAKE_CUDA20_COMPILE_FEATURES}) endif() @@ -153,6 +163,7 @@ function(cmake_determine_compile_features lang) ${CMAKE_CUDA17_COMPILE_FEATURES} ${CMAKE_CUDA20_COMPILE_FEATURES} ${CMAKE_CUDA23_COMPILE_FEATURES} + ${CMAKE_CUDA26_COMPILE_FEATURES} ) endif() @@ -163,6 +174,7 @@ function(cmake_determine_compile_features lang) set(CMAKE_CUDA17_COMPILE_FEATURES ${CMAKE_CUDA17_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_CUDA20_COMPILE_FEATURES ${CMAKE_CUDA20_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_CUDA23_COMPILE_FEATURES ${CMAKE_CUDA23_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_CUDA26_COMPILE_FEATURES ${CMAKE_CUDA26_COMPILE_FEATURES} PARENT_SCOPE) message(CHECK_PASS "done") @@ -175,6 +187,8 @@ function(cmake_determine_compile_features lang) set(CMAKE_HIP17_COMPILE_FEATURES) set(CMAKE_HIP20_COMPILE_FEATURES) set(CMAKE_HIP23_COMPILE_FEATURES) + set(CMAKE_HIP26_COMPILE_FEATURES) + include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake") @@ -185,6 +199,9 @@ function(cmake_determine_compile_features lang) return() endif() + if (CMAKE_HIP23_COMPILE_FEATURES AND CMAKE_HIP26_COMPILE_FEATURES) + list(REMOVE_ITEM CMAKE_HIP26_COMPILE_FEATURES ${CMAKE_HIP23_COMPILE_FEATURES}) + endif() if (CMAKE_HIP20_COMPILE_FEATURES AND CMAKE_HIP23_COMPILE_FEATURES) list(REMOVE_ITEM CMAKE_HIP23_COMPILE_FEATURES ${CMAKE_HIP20_COMPILE_FEATURES}) endif() @@ -209,6 +226,7 @@ function(cmake_determine_compile_features lang) ${CMAKE_HIP17_COMPILE_FEATURES} ${CMAKE_HIP20_COMPILE_FEATURES} ${CMAKE_HIP23_COMPILE_FEATURES} + ${CMAKE_HIP26_COMPILE_FEATURES} ) endif() @@ -219,6 +237,7 @@ function(cmake_determine_compile_features lang) set(CMAKE_HIP17_COMPILE_FEATURES ${CMAKE_HIP17_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_HIP20_COMPILE_FEATURES ${CMAKE_HIP20_COMPILE_FEATURES} PARENT_SCOPE) set(CMAKE_HIP23_COMPILE_FEATURES ${CMAKE_HIP23_COMPILE_FEATURES} PARENT_SCOPE) + set(CMAKE_HIP26_COMPILE_FEATURES ${CMAKE_HIP26_COMPILE_FEATURES} PARENT_SCOPE) message(CHECK_PASS "done") diff --git a/Modules/CMakeDetermineCompilerABI.cmake b/Modules/CMakeDetermineCompilerABI.cmake index 82a6d21..053effa 100644 --- a/Modules/CMakeDetermineCompilerABI.cmake +++ b/Modules/CMakeDetermineCompilerABI.cmake @@ -55,7 +55,7 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) set(ENV{LANG} C) try_compile(CMAKE_${lang}_ABI_COMPILED - ${CMAKE_BINARY_DIR} ${src} + SOURCES ${src} CMAKE_FLAGS ${CMAKE_FLAGS} # Ignore unused flags when we are just determining the ABI. "--no-warn-unused-cli" @@ -149,7 +149,8 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) if(CMAKE_${lang}_VERBOSE_FLAG) CMAKE_PARSE_IMPLICIT_LINK_INFO("${OUTPUT}" implicit_libs implicit_dirs implicit_fwks log "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}" - COMPUTE_IMPLICIT_OBJECTS implicit_objs) + COMPUTE_IMPLICIT_OBJECTS implicit_objs + LANGUAGE ${lang}) file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Parsed ${lang} implicit link information from above output:\n${log}\n\n") endif() @@ -161,8 +162,9 @@ function(CMAKE_DETERMINE_COMPILER_ABI lang src) message(CHECK_START "Determine Intel Fortran Compiler Implicit Link Path") # Build a sample project which reports symbols. try_compile(IFORT_LIB_PATH_COMPILED - ${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath - ${CMAKE_ROOT}/Modules/IntelVSImplicitPath + PROJECT IntelFortranImplicit + SOURCE_DIR ${CMAKE_ROOT}/Modules/IntelVSImplicitPath + BINARY_DIR ${CMAKE_BINARY_DIR}/CMakeFiles/IntelVSImplicitPath IntelFortranImplicit CMAKE_FLAGS "-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}" diff --git a/Modules/CMakeDetermineCompilerId.cmake b/Modules/CMakeDetermineCompilerId.cmake index 2b19736..6b58549 100644 --- a/Modules/CMakeDetermineCompilerId.cmake +++ b/Modules/CMakeDetermineCompilerId.cmake @@ -720,7 +720,7 @@ Id flags: ${testflags} ${CMAKE_${lang}_COMPILER_ID_FLAGS_ALWAYS} OR CMAKE_${lang}_COMPILER_ID_OUTPUT MATCHES "warning #5117: Bad # preprocessor line" ) # Compilation failed. - set(MSG + string(APPEND _CMAKE_DETERMINE_COMPILER_ID_BUILD_MSG "Compiling the ${lang} compiler identification source file \"${src}\" failed. ${COMPILER_DESCRIPTION} The output was: @@ -736,7 +736,11 @@ ${CMAKE_${lang}_COMPILER_ID_OUTPUT} # Some languages may know the correct/desired set of flags and want to fail right away if they don't work. # This is currently only used by CUDA. if(__compiler_id_require_success) - message(FATAL_ERROR "${MSG}") + message(FATAL_ERROR "${_CMAKE_DETERMINE_COMPILER_ID_BUILD_MSG}") + else() + # Build up the outputs for compiler detection attempts so that users + # can see all set of flags tried, instead of just last + set(_CMAKE_DETERMINE_COMPILER_ID_BUILD_MSG "${_CMAKE_DETERMINE_COMPILER_ID_BUILD_MSG}" PARENT_SCOPE) endif() # No output files should be inspected. diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index 650c87a..087c0f6 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -44,17 +44,14 @@ else() # finally list compilers to try if(NOT CMAKE_Fortran_COMPILER_INIT) # Known compilers: - # f77/f90/f95: generic compiler names # ftn: Cray fortran compiler wrapper - # g77: GNU Fortran 77 compiler # gfortran: putative GNU Fortran 95+ compiler (in progress) - # fort77: native F77 compiler under HP-UX (and some older Crays) - # frt: Fujitsu F77 compiler + # frt: Fujitsu Fortran compiler # pathf90/pathf95/pathf2003: PathScale Fortran compiler - # pgf77/pgf90/pgf95/pgfortran: Portland Group F77/F90/F95 compilers + # pgfortran: Portland Group Fortran compilers # nvfortran: NVHPC Fotran compiler # flang: Flang Fortran compiler - # xlf/xlf90/xlf95: IBM (AIX) F77/F90/F95 compilers + # xlf: IBM (AIX) Fortran compiler # lf95: Lahey-Fujitsu F95 compiler # fl32: Microsoft Fortran 77 "PowerStation" compiler # af77: Apogee F77 compiler for Intergraph hardware running CLIX @@ -62,31 +59,20 @@ else() # fort: Compaq (now HP) Fortran 90/95 compiler for Tru64 and Linux/Alpha # ifx: Intel Fortran LLVM-based compiler # ifort: Intel Classic Fortran compiler - # ifc: Intel Fortran 95 compiler for Linux/x86 - # efc: Intel Fortran 95 compiler for IA64 # nagfor: NAG Fortran compiler # - # The order is 95 or newer compilers first, then 90, - # then 77 or older compilers, gnu is always last in the group, + # GNU is last to be searched, # so if you paid for a compiler it is picked by default. - if(CMAKE_HOST_WIN32) - set(CMAKE_Fortran_COMPILER_LIST - ifort ifx pgf95 pgfortran nvfortran lf95 fort - flang gfortran gfortran-4 g95 f90 pgf90 - pgf77 g77 f77 nag - ) - else() - set(CMAKE_Fortran_COMPILER_LIST - ftn - ifort ifc ifx efc pgf95 pgfortran nvfortran lf95 xlf95 fort - flang lfortran gfortran gfortran-4 g95 f90 pgf90 - frt pgf77 xlf g77 f77 nag - ) - endif() + set(CMAKE_Fortran_COMPILER_LIST + ftn + ifx ifort nvfortran pgfortran lf95 xlf fort + flang lfortran frt nagfor + gfortran + ) # Vendor-specific compiler names. set(_Fortran_COMPILER_NAMES_LCC lfortran gfortran) - set(_Fortran_COMPILER_NAMES_GNU gfortran gfortran-4 g95 g77) + set(_Fortran_COMPILER_NAMES_GNU gfortran) set(_Fortran_COMPILER_NAMES_Intel ifort ifc efc ifx) set(_Fortran_COMPILER_NAMES_Absoft af95 af90 af77) set(_Fortran_COMPILER_NAMES_PGI pgf95 pgfortran pgf90 pgf77) diff --git a/Modules/CMakeDetermineHIPCompiler.cmake b/Modules/CMakeDetermineHIPCompiler.cmake index 7b7d7a3..6294d04 100644 --- a/Modules/CMakeDetermineHIPCompiler.cmake +++ b/Modules/CMakeDetermineHIPCompiler.cmake @@ -86,6 +86,7 @@ if(NOT CMAKE_HIP_COMPILER_ROCM_ROOT AND CMAKE_HIP_COMPILER_ID STREQUAL "Clang") if(_CMAKE_HIP_COMPILER_RESULT EQUAL 0 AND _CMAKE_HIP_COMPILER_STDERR MATCHES "Found HIP installation: *([^,]*)[,\n]") set(CMAKE_HIP_COMPILER_ROCM_ROOT "${CMAKE_MATCH_1}") + file(TO_CMAKE_PATH "${CMAKE_HIP_COMPILER_ROCM_ROOT}" CMAKE_HIP_COMPILER_ROCM_ROOT) endif() endif() if(NOT CMAKE_HIP_COMPILER_ROCM_ROOT) diff --git a/Modules/CMakeDetermineVSServicePack.cmake b/Modules/CMakeDetermineVSServicePack.cmake index 53868d2..0d360b5 100644 --- a/Modules/CMakeDetermineVSServicePack.cmake +++ b/Modules/CMakeDetermineVSServicePack.cmake @@ -105,8 +105,7 @@ function(_DetermineVSServicePack_CheckVersionWithTryCompile _SUCCESS_VAR _VERSI try_compile( _CompileResult - "${CMAKE_BINARY_DIR}" - "${CMAKE_BINARY_DIR}/return0.cc" + SOURCES "${CMAKE_BINARY_DIR}/return0.cc" OUTPUT_VARIABLE _output COPY_FILE "${CMAKE_BINARY_DIR}/return0.cc") @@ -128,8 +127,7 @@ function(_DetermineVSServicePack_CheckVersionWithTryRun _SUCCESS_VAR _VERSION_V try_run( _RunResult _CompileResult - "${CMAKE_BINARY_DIR}" - "${CMAKE_BINARY_DIR}/return0.cc" + SOURCES "${CMAKE_BINARY_DIR}/return0.cc" RUN_OUTPUT_VARIABLE _runoutput ) diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake index a6bd0d1..2ac8879 100644 --- a/Modules/CMakeFindBinUtils.cmake +++ b/Modules/CMakeFindBinUtils.cmake @@ -170,7 +170,7 @@ else() if("${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" STREQUAL Clang) if("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC") list(PREPEND _CMAKE_LINKER_NAMES "lld-link") - else() + elseif(NOT APPLE) list(PREPEND _CMAKE_LINKER_NAMES "ld.lld") endif() if(APPLE) diff --git a/Modules/CMakeFindFrameworks.cmake b/Modules/CMakeFindFrameworks.cmake index 8906f48..1aa3929 100644 --- a/Modules/CMakeFindFrameworks.cmake +++ b/Modules/CMakeFindFrameworks.cmake @@ -17,12 +17,19 @@ if(NOT CMAKE_FIND_FRAMEWORKS_INCLUDED) macro(CMAKE_FIND_FRAMEWORKS fwk) set(${fwk}_FRAMEWORKS) if(APPLE) + # 'Frameworks' directory from Brew (Apple Silicon and Intel) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") + set(_brew_framework_path /opt/homebrew/Frameworks) + else() + set(_brew_framework_path /usr/local/Frameworks) + endif() + file(TO_CMAKE_PATH "$ENV{CMAKE_FRAMEWORK_PATH}" _cmff_CMAKE_FRAMEWORK_PATH) set(_cmff_search_paths ${CMAKE_FRAMEWORK_PATH} ${_cmff_CMAKE_FRAMEWORK_PATH} ~/Library/Frameworks - /usr/local/Frameworks + ${_brew_framework_path} /Library/Frameworks /System/Library/Frameworks /Network/Library/Frameworks diff --git a/Modules/CMakeHIPInformation.cmake b/Modules/CMakeHIPInformation.cmake index 4c57677..33f8697 100644 --- a/Modules/CMakeHIPInformation.cmake +++ b/Modules/CMakeHIPInformation.cmake @@ -143,7 +143,7 @@ set(CMAKE_HIP_INFORMATION_LOADED 1) # Load the file and find the relevant HIP runtime. if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) set(hip-lang_DIR "${CMAKE_HIP_COMPILER_ROCM_ROOT}/lib/cmake/hip-lang") - find_package(hip-lang CONFIG QUIET NO_DEFAULT_PATH) + find_package(hip-lang CONFIG QUIET NO_DEFAULT_PATH REQUIRED) endif() if(DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) list(APPEND CMAKE_HIP_RUNTIME_LIBRARIES_STATIC ${_CMAKE_HIP_DEVICE_RUNTIME_TARGET}) diff --git a/Modules/CMakeParseImplicitLinkInfo.cmake b/Modules/CMakeParseImplicitLinkInfo.cmake index 6bdefde..1773dc4 100644 --- a/Modules/CMakeParseImplicitLinkInfo.cmake +++ b/Modules/CMakeParseImplicitLinkInfo.cmake @@ -22,7 +22,7 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj set(log "") set(keywordArgs) - set(oneValueArgs COMPUTE_IMPLICIT_OBJECTS) + set(oneValueArgs COMPUTE_IMPLICIT_OBJECTS LANGUAGE) set(multiValueArgs ) cmake_parse_arguments(EXTRA_PARSE "${keywordArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) @@ -76,6 +76,11 @@ function(CMAKE_PARSE_IMPLICIT_LINK_INFO text lib_var dir_var fwk_var log_var obj endif() endif() set(is_msvc 0) + if(EXTRA_PARSE_LANGUAGE AND + ("x${CMAKE_${EXTRA_PARSE_LANGUAGE}_ID}" STREQUAL "xMSVC" OR + "x${CMAKE_${EXTRA_PARSE_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC")) + set(is_msvc 1) + endif() set(search_static 0) if("${cmd}" MATCHES "${linker_regex}") string(APPEND log " link line: [${line}]\n") diff --git a/Modules/CMakePlatformId.h.in b/Modules/CMakePlatformId.h.in index 06f5ecd..32b7166 100644 --- a/Modules/CMakePlatformId.h.in +++ b/Modules/CMakePlatformId.h.in @@ -242,6 +242,30 @@ # elif defined(__ADSPBLACKFIN__) # define ARCHITECTURE_ID "Blackfin" +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + #else # define ARCHITECTURE_ID #endif diff --git a/Modules/CMakeSwiftInformation.cmake b/Modules/CMakeSwiftInformation.cmake index ecad1d5..16726d2 100644 --- a/Modules/CMakeSwiftInformation.cmake +++ b/Modules/CMakeSwiftInformation.cmake @@ -65,7 +65,7 @@ set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -libc MD) set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -libc MTd) set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -libc MDd) -set(CMAKE_Swift_FLAGS_DEBUG_INIT "-g") +set(CMAKE_Swift_FLAGS_DEBUG_INIT "-Onone -g") set(CMAKE_Swift_FLAGS_RELEASE_INIT "-O") set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT "-O -g") set(CMAKE_Swift_FLAGS_MINSIZEREL_INIT "-Osize") diff --git a/Modules/CMakeSystemSpecificInformation.cmake b/Modules/CMakeSystemSpecificInformation.cmake index e045932..b5dc8d3 100644 --- a/Modules/CMakeSystemSpecificInformation.cmake +++ b/Modules/CMakeSystemSpecificInformation.cmake @@ -16,6 +16,8 @@ set(UNIX ) set(CYGWIN ) set(MSYS ) set(WIN32 ) +set(BSD ) +set(LINUX ) function(_cmake_record_install_prefix ) set(_CMAKE_SYSTEM_PREFIX_PATH_INSTALL_PREFIX_VALUE "${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE) diff --git a/Modules/CMakeTestCCompiler.cmake b/Modules/CMakeTestCCompiler.cmake index ae5aa27..a706767 100644 --- a/Modules/CMakeTestCCompiler.cmake +++ b/Modules/CMakeTestCCompiler.cmake @@ -38,7 +38,7 @@ endif() if(NOT CMAKE_C_COMPILER_WORKS) PrintTestCompilerStatus("C") __TestCompiler_setTryCompileTargetType() - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c + string(CONCAT __TestCompiler_testCCompilerSource "#ifdef __cplusplus\n" "# error \"The CMAKE_C_COMPILER is set to a C++ compiler\"\n" "#endif\n" @@ -53,9 +53,10 @@ if(NOT CMAKE_C_COMPILER_WORKS) # Clear result from normal variable. unset(CMAKE_C_COMPILER_WORKS) # Puts test result in cache variable. - try_compile(CMAKE_C_COMPILER_WORKS ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler.c + try_compile(CMAKE_C_COMPILER_WORKS + SOURCE_FROM_VAR testCCompiler.c __TestCompiler_testCCompilerSource OUTPUT_VARIABLE __CMAKE_C_COMPILER_OUTPUT) + unset(__TestCompiler_testCCompilerSource) # Move result from cache to normal variable. set(CMAKE_C_COMPILER_WORKS ${CMAKE_C_COMPILER_WORKS}) unset(CMAKE_C_COMPILER_WORKS CACHE) diff --git a/Modules/CMakeTestCSharpCompiler.cmake b/Modules/CMakeTestCSharpCompiler.cmake index adea250..1c9e249 100644 --- a/Modules/CMakeTestCSharpCompiler.cmake +++ b/Modules/CMakeTestCSharpCompiler.cmake @@ -12,8 +12,6 @@ include(CMakeTestCompilerCommon) unset(CMAKE_CSharp_COMPILER_WORKS CACHE) -set(test_compile_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCSharpCompiler.cs") - # This file is used by EnableLanguage in cmGlobalGenerator to # determine that the selected C# compiler can actually compile # and link the most basic of programs. If not, a fatal error @@ -23,19 +21,21 @@ if(NOT CMAKE_CSharp_COMPILER_WORKS) # Don't call PrintTestCompilerStatus() because the "C#" we want to pass # as the LANG doesn't match with the variable name "CMAKE_CSharp_COMPILER" message(CHECK_START "Check for working C# compiler: ${CMAKE_CSharp_COMPILER}") - file(WRITE "${test_compile_file}" - "namespace Test {" - " public class CSharp {" - " static void Main(string[] args) {}" - " }" - "}" + string(CONCAT __TestCompiler_testCSharpCompilerSource + "namespace Test {\n" + " public class CSharp {\n" + " static void Main(string[] args) {}\n" + " }\n" + "}\n" ) # Clear result from normal variable. unset(CMAKE_CSharp_COMPILER_WORKS) # Puts test result in cache variable. - try_compile(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_BINARY_DIR} "${test_compile_file}" + try_compile(CMAKE_CSharp_COMPILER_WORKS + SOURCE_FROM_VAR testCSharpCompiler.cs __TestCompiler_testCSharpCompilerSource OUTPUT_VARIABLE __CMAKE_CSharp_COMPILER_OUTPUT ) + unset(__TestCompiler_testCSharpCompilerSource) # Move result from cache to normal variable. set(CMAKE_CSharp_COMPILER_WORKS ${CMAKE_CSharp_COMPILER_WORKS}) unset(CMAKE_CSharp_COMPILER_WORKS CACHE) diff --git a/Modules/CMakeTestCUDACompiler.cmake b/Modules/CMakeTestCUDACompiler.cmake index 853d655..f2fa6ea 100644 --- a/Modules/CMakeTestCUDACompiler.cmake +++ b/Modules/CMakeTestCUDACompiler.cmake @@ -76,7 +76,7 @@ endif() # any makefiles or projects. if(NOT CMAKE_CUDA_COMPILER_WORKS) PrintTestCompilerStatus("CUDA") - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.cu + string(CONCAT __TestCompiler_testCudaCompilerSource "#ifndef __CUDACC__\n" "# error \"The CMAKE_CUDA_COMPILER is set to an invalid CUDA compiler\"\n" "#endif\n" @@ -86,9 +86,10 @@ if(NOT CMAKE_CUDA_COMPILER_WORKS) unset(CMAKE_CUDA_COMPILER_WORKS) # Puts test result in cache variable. - try_compile(CMAKE_CUDA_COMPILER_WORKS ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.cu + try_compile(CMAKE_CUDA_COMPILER_WORKS + SOURCE_FROM_VAR main.cu __TestCompiler_testCudaCompilerSource OUTPUT_VARIABLE __CMAKE_CUDA_COMPILER_OUTPUT) + unset(__TestCompiler_testCudaCompilerSource) # Move result from cache to normal variable. set(CMAKE_CUDA_COMPILER_WORKS ${CMAKE_CUDA_COMPILER_WORKS}) diff --git a/Modules/CMakeTestCXXCompiler.cmake b/Modules/CMakeTestCXXCompiler.cmake index bbe3533..fa4016a 100644 --- a/Modules/CMakeTestCXXCompiler.cmake +++ b/Modules/CMakeTestCXXCompiler.cmake @@ -38,7 +38,7 @@ endif() if(NOT CMAKE_CXX_COMPILER_WORKS) PrintTestCompilerStatus("CXX") __TestCompiler_setTryCompileTargetType() - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCXXCompiler.cxx + string(CONCAT __TestCompiler_testCXXCompilerSource "#ifndef __cplusplus\n" "# error \"The CMAKE_CXX_COMPILER is set to a C compiler\"\n" "#endif\n" @@ -46,9 +46,10 @@ if(NOT CMAKE_CXX_COMPILER_WORKS) # Clear result from normal variable. unset(CMAKE_CXX_COMPILER_WORKS) # Puts test result in cache variable. - try_compile(CMAKE_CXX_COMPILER_WORKS ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCXXCompiler.cxx + try_compile(CMAKE_CXX_COMPILER_WORKS + SOURCE_FROM_VAR testCXXCompiler.cxx __TestCompiler_testCXXCompilerSource OUTPUT_VARIABLE __CMAKE_CXX_COMPILER_OUTPUT) + unset(__TestCompiler_testCXXCompilerSource) # Move result from cache to normal variable. set(CMAKE_CXX_COMPILER_WORKS ${CMAKE_CXX_COMPILER_WORKS}) unset(CMAKE_CXX_COMPILER_WORKS CACHE) @@ -56,7 +57,7 @@ if(NOT CMAKE_CXX_COMPILER_WORKS) if(NOT CMAKE_CXX_COMPILER_WORKS) PrintTestCompilerResult(CHECK_FAIL "broken") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if the CXX compiler works failed with " + "Determining if the C++ compiler works failed with " "the following output:\n${__CMAKE_CXX_COMPILER_OUTPUT}\n\n") string(REPLACE "\n" "\n " _output "${__CMAKE_CXX_COMPILER_OUTPUT}") message(FATAL_ERROR "The C++ compiler\n \"${CMAKE_CXX_COMPILER}\"\n" @@ -66,7 +67,7 @@ if(NOT CMAKE_CXX_COMPILER_WORKS) endif() PrintTestCompilerResult(CHECK_PASS "works") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Determining if the CXX compiler works passed with " + "Determining if the C++ compiler works passed with " "the following output:\n${__CMAKE_CXX_COMPILER_OUTPUT}\n\n") endif() diff --git a/Modules/CMakeTestFortranCompiler.cmake b/Modules/CMakeTestFortranCompiler.cmake index 579f83f..e6d1f6d 100644 --- a/Modules/CMakeTestFortranCompiler.cmake +++ b/Modules/CMakeTestFortranCompiler.cmake @@ -38,7 +38,7 @@ endif() # any makefiles or projects. if(NOT CMAKE_Fortran_COMPILER_WORKS) PrintTestCompilerStatus("Fortran") - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f " + set(__TestCompiler_testFortranCompilerSource " PROGRAM TESTFortran PRINT *, 'Hello' END @@ -46,9 +46,10 @@ if(NOT CMAKE_Fortran_COMPILER_WORKS) # Clear result from normal variable. unset(CMAKE_Fortran_COMPILER_WORKS) # Puts test result in cache variable. - try_compile(CMAKE_Fortran_COMPILER_WORKS ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f + try_compile(CMAKE_Fortran_COMPILER_WORKS + SOURCE_FROM_VAR testFortranCompiler.f __TestCompiler_testFortranCompilerSource OUTPUT_VARIABLE OUTPUT) + unset(__TestCompiler_testFortranCompilerSource) # Move result from cache to normal variable. set(CMAKE_Fortran_COMPILER_WORKS ${CMAKE_Fortran_COMPILER_WORKS}) unset(CMAKE_Fortran_COMPILER_WORKS CACHE) @@ -72,14 +73,15 @@ endif() # Test for Fortran 90 support by using an f90-specific construct. if(NOT DEFINED CMAKE_Fortran_COMPILER_SUPPORTS_F90) message(CHECK_START "Checking whether ${CMAKE_Fortran_COMPILER} supports Fortran 90") - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompilerF90.f90 " + set(__TestCompiler_testFortranCompilerSource " PROGRAM TESTFortran90 integer stop ; stop = 1 ; do while ( stop .eq. 0 ) ; end do END PROGRAM TESTFortran90 ") - try_compile(CMAKE_Fortran_COMPILER_SUPPORTS_F90 ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompilerF90.f90 + try_compile(CMAKE_Fortran_COMPILER_SUPPORTS_F90 + SOURCE_FROM_VAR testFortranCompilerF90.f90 __TestCompiler_testFortranCompilerF90Source OUTPUT_VARIABLE OUTPUT) + unset(__TestCompiler_testFortranCompilerF90Source) if(CMAKE_Fortran_COMPILER_SUPPORTS_F90) message(CHECK_PASS "yes") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log diff --git a/Modules/CMakeTestHIPCompiler.cmake b/Modules/CMakeTestHIPCompiler.cmake index ecbfa7f..1da0ae4 100644 --- a/Modules/CMakeTestHIPCompiler.cmake +++ b/Modules/CMakeTestHIPCompiler.cmake @@ -41,7 +41,7 @@ endif() if(NOT CMAKE_HIP_COMPILER_WORKS) PrintTestCompilerStatus("HIP") __TestCompiler_setTryCompileTargetType() - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testHIPCompiler.hip + string(CONCAT __TestCompiler_testHIPCompilerSource "#ifndef __HIP__\n" "# error \"The CMAKE_HIP_COMPILER is set to a C/CXX compiler\"\n" "#endif\n" @@ -49,9 +49,10 @@ if(NOT CMAKE_HIP_COMPILER_WORKS) # Clear result from normal variable. unset(CMAKE_HIP_COMPILER_WORKS) # Puts test result in cache variable. - try_compile(CMAKE_HIP_COMPILER_WORKS ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testHIPCompiler.hip + try_compile(CMAKE_HIP_COMPILER_WORKS + SOURCE_FROM_VAR testHIPCompiler.hip __TestCompiler_testHIPCompilerSource OUTPUT_VARIABLE __CMAKE_HIP_COMPILER_OUTPUT) + unset(__TestCompiler_testHIPCompilerSource) # Move result from cache to normal variable. set(CMAKE_HIP_COMPILER_WORKS ${CMAKE_HIP_COMPILER_WORKS}) unset(CMAKE_HIP_COMPILER_WORKS CACHE) diff --git a/Modules/CMakeTestOBJCCompiler.cmake b/Modules/CMakeTestOBJCCompiler.cmake index 20d1f8b..bbc90a7 100644 --- a/Modules/CMakeTestOBJCCompiler.cmake +++ b/Modules/CMakeTestOBJCCompiler.cmake @@ -38,7 +38,7 @@ endif() if(NOT CMAKE_OBJC_COMPILER_WORKS) PrintTestCompilerStatus("OBJC") __TestCompiler_setTryCompileTargetType() - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m + string(CONCAT __TestCompiler_testObjCCompilerSource "#ifdef __cplusplus\n" "# error \"The CMAKE_OBJC_COMPILER is set to a C++ compiler\"\n" "#endif\n" @@ -50,9 +50,10 @@ if(NOT CMAKE_OBJC_COMPILER_WORKS) # Clear result from normal variable. unset(CMAKE_OBJC_COMPILER_WORKS) # Puts test result in cache variable. - try_compile(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m + try_compile(CMAKE_OBJC_COMPILER_WORKS + SOURCE_FROM_VAR testObjCCompiler.m __TestCompiler_testObjCCompilerSource OUTPUT_VARIABLE __CMAKE_OBJC_COMPILER_OUTPUT) + unset(__TestCompiler_testObjCCompilerSource) # Move result from cache to normal variable. set(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_OBJC_COMPILER_WORKS}) unset(CMAKE_OBJC_COMPILER_WORKS CACHE) diff --git a/Modules/CMakeTestOBJCXXCompiler.cmake b/Modules/CMakeTestOBJCXXCompiler.cmake index 4f7185f..aceb939 100644 --- a/Modules/CMakeTestOBJCXXCompiler.cmake +++ b/Modules/CMakeTestOBJCXXCompiler.cmake @@ -38,7 +38,7 @@ endif() if(NOT CMAKE_OBJCXX_COMPILER_WORKS) PrintTestCompilerStatus("OBJCXX") __TestCompiler_setTryCompileTargetType() - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm + string(CONCAT __TestCompiler_testObjCXXCompilerSource "#ifndef __cplusplus\n" "# error \"The CMAKE_OBJCXX_COMPILER is set to a C compiler\"\n" "#endif\n" @@ -49,9 +49,10 @@ if(NOT CMAKE_OBJCXX_COMPILER_WORKS) # Clear result from normal variable. unset(CMAKE_OBJCXX_COMPILER_WORKS) # Puts test result in cache variable. - try_compile(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm + try_compile(CMAKE_OBJCXX_COMPILER_WORKS + SOURCE_FROM_VAR testObjCXXCompiler.mm __TestCompiler_testObjCXXCompilerSource OUTPUT_VARIABLE __CMAKE_OBJCXX_COMPILER_OUTPUT) + unset(__TestCompiler_testObjCXXCompilerSource) # Move result from cache to normal variable. set(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_OBJCXX_COMPILER_WORKS}) unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE) diff --git a/Modules/CMakeTestSwiftCompiler.cmake b/Modules/CMakeTestSwiftCompiler.cmake index 2f2546f..88a864c 100644 --- a/Modules/CMakeTestSwiftCompiler.cmake +++ b/Modules/CMakeTestSwiftCompiler.cmake @@ -21,13 +21,12 @@ unset(CMAKE_Swift_COMPILER_WORKS CACHE) # any makefiles or projects. if(NOT CMAKE_Swift_COMPILER_WORKS) PrintTestCompilerStatus("Swift") - file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.swift - "print(\"CMake\")\n") # Clear result from normal variable. unset(CMAKE_Swift_COMPILER_WORKS) # Puts test result in cache variable. - try_compile(CMAKE_Swift_COMPILER_WORKS ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.swift + set(__CMAKE_Swift_TEST_SOURCE "print(\"CMake\")\n") + try_compile(CMAKE_Swift_COMPILER_WORKS + SOURCE_FROM_VAR main.swift __CMAKE_Swift_TEST_SOURCE OUTPUT_VARIABLE __CMAKE_Swift_COMPILER_OUTPUT) # Move result from cache to normal variable. set(CMAKE_Swift_COMPILER_WORKS ${CMAKE_Swift_COMPILER_WORKS}) @@ -64,4 +63,5 @@ else() include(${CMAKE_PLATFORM_INFO_DIR}/CMakeSwiftCompiler.cmake) endif() +unset(__CMAKE_Swift_TEST_SOURCE) unset(__CMAKE_Swift_COMPILER_OUTPUT) diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index 4934934..828d9ca 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -53,9 +53,9 @@ Here's how it works: * :manual:`cpack <cpack(1)>` runs * it includes ``CPackConfig.cmake`` -* it iterates over the generators given by the ``-G`` command line option, - or if no such option was specified, over the list of generators given by - the :variable:`CPACK_GENERATOR` variable set in the ``CPackConfig.cmake`` +* it iterates over the generators given by the :option:`-G <cpack -G>` command + line option, or if no such option was specified, over the list of generators + given by the :variable:`CPACK_GENERATOR` variable set in the ``CPackConfig.cmake`` input file. * foreach generator, it then @@ -246,9 +246,9 @@ installers. The most commonly-used variables are: List of CPack generators to use. If not specified, CPack will create a set of options following the naming pattern :variable:`CPACK_BINARY_<GENNAME>` (e.g. ``CPACK_BINARY_NSIS``) allowing - the user to enable/disable individual generators. If the ``-G`` option is - given on the :manual:`cpack <cpack(1)>` command line, it will override this - variable and any ``CPACK_BINARY_<GENNAME>`` options. + the user to enable/disable individual generators. If the :option:`-G <cpack -G>` + option is given on the :manual:`cpack <cpack(1)>` command line, it will override + this variable and any ``CPACK_BINARY_<GENNAME>`` options. .. variable:: CPACK_OUTPUT_CONFIG_FILE @@ -469,7 +469,35 @@ The following variables are for advanced uses of CPack: generates (when :variable:`CPACK_GENERATOR` is not set) a set of CMake options (see CMake :command:`option` command) which may then be used to select the CPack generator(s) to be used when building the ``package`` - target or when running :manual:`cpack <cpack(1)>` without the ``-G`` option. + target or when running :manual:`cpack <cpack(1)>` without the + :option:`-G <cpack -G>` option. + +.. variable:: CPACK_READELF_EXECUTABLE + + .. versionadded:: 3.25 + + Specify the ``readelf`` executable path used by CPack. + The default value will be ``CMAKE_READELF`` when set. Otherwise, + the default value will be empty and CPack will use :command:`find_program` + to determine the ``readelf`` path when needed. + +.. variable:: CPACK_OBJCOPY_EXECUTABLE + + .. versionadded:: 3.25 + + Specify the ``objcopy`` executable path used by CPack. + The default value will be ``CMAKE_OBJCOPY`` when set. Otherwise, + the default value will be empty and CPack will use :command:`find_program` + to determine the ``objcopy`` path when needed. + +.. variable:: CPACK_OBJDUMP_EXECUTABLE + + .. versionadded:: 3.25 + + Specify the ``objdump`` executable path used by CPack. + The default value will be ``CMAKE_OBJDUMP`` when set. Otherwise, + the default value will be empty and CPack will use :command:`find_program` + to determine the ``objdump`` path when needed. #]=======================================================================] @@ -590,6 +618,16 @@ _cpack_set_default(CPACK_RESOURCE_FILE_WELCOME _cpack_set_default(CPACK_MODULE_PATH "${CMAKE_MODULE_PATH}") +if(CMAKE_READELF) + _cpack_set_default(CPACK_READELF_EXECUTABLE "${CMAKE_READELF}") +endif() +if(CMAKE_OBJCOPY) + _cpack_set_default(CPACK_OBJCOPY_EXECUTABLE "${CMAKE_OBJCOPY}") +endif() +if(CMAKE_OBJDUMP) + _cpack_set_default(CPACK_OBJDUMP_EXECUTABLE "${CMAKE_OBJDUMP}") +endif() + # Set default directory creation permissions mode if(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS) _cpack_set_default(CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS diff --git a/Modules/CPackIFW.cmake b/Modules/CPackIFW.cmake index a4bfe1d..efe6999 100644 --- a/Modules/CPackIFW.cmake +++ b/Modules/CPackIFW.cmake @@ -439,37 +439,55 @@ set(_CPACK_IFW_PREFIXES "QtIFW-") set(_CPACK_IFW_VERSIONS + "4.4.2" + "4.4.1" + "4.4.0" "4.4" + "4.3.0" "4.3" + "4.2.0" "4.2" + "4.1.1" + "4.1.0" "4.1" + "4.0.1" + "4.0.0" "4.0" - "3.2" + "3.2.3" + "3.2.2" + "3.2.1" "3.2.0" - "3.1" + "3.2" + "3.1.1" "3.1.0" - "3.0" + "3.1" + "3.0.6" + "3.0.4" + "3.0.3" + "3.0.2" + "3.0.1" "3.0.0" - "2.3" + "3.0" "2.3.0" - "2.2" + "2.3" "2.2.0" - "2.1" + "2.2" "2.1.0" - "2.0" + "2.1" "2.0.5" "2.0.3" "2.0.2" "2.0.1" "2.0.0" - "1.6" + "2.0" "1.6.0" - "1.5" + "1.6" "1.5.0" - "1.4" + "1.5" "1.4.0" - "1.3" - "1.3.0") + "1.4" + "1.3.0" + "1.3") set(_CPACK_IFW_SUFFIXES "bin") foreach(_CPACK_IFW_PREFIX ${_CPACK_IFW_PREFIXES}) diff --git a/Modules/CTest.cmake b/Modules/CTest.cmake index 8f8ebb4..16283d6 100644 --- a/Modules/CTest.cmake +++ b/Modules/CTest.cmake @@ -33,7 +33,7 @@ file at the top of the project with content such as:: (the CDash server can provide the file to a project administrator who configures ``MyProject``). Settings in the config file are shared by both this ``CTest`` module and the :manual:`ctest(1)` command-line -:ref:`Dashboard Client` mode (``ctest -S``). +:ref:`Dashboard Client` mode (:option:`ctest -S`). While building a project for submission to CDash, CTest scans the build output for errors and warnings and reports them with surrounding diff --git a/Modules/CTestTargets.cmake b/Modules/CTestTargets.cmake index 838fbbf..b91b48e 100644 --- a/Modules/CTestTargets.cmake +++ b/Modules/CTestTargets.cmake @@ -86,7 +86,7 @@ if(NOT _CTEST_TARGETS_ADDED) # or "RUN_TESTS" target: if(CTEST_TEST_TARGET_ALIAS) add_custom_target(${CTEST_TEST_TARGET_ALIAS} - ${CMAKE_CTEST_COMMAND} ${__conf_types} + ${CMAKE_CTEST_COMMAND} ${CMAKE_CTEST_ARGUMENTS} ${__conf_types} USES_TERMINAL ) endif() diff --git a/Modules/CTestUseLaunchers.cmake b/Modules/CTestUseLaunchers.cmake index 23a206b..5c544f8 100644 --- a/Modules/CTestUseLaunchers.cmake +++ b/Modules/CTestUseLaunchers.cmake @@ -11,7 +11,7 @@ CTestUseLaunchers is automatically included when you include(CTest). However, it is split out into its own module file so projects can use the CTEST_USE_LAUNCHERS functionality independently. -To use launchers, set CTEST_USE_LAUNCHERS to ON in a ctest -S +To use launchers, set CTEST_USE_LAUNCHERS to ON in a :option:`ctest -S` dashboard script, and then also set it in the cache of the configured project. Both cmake and ctest need to know the value of it for the launchers to work properly. CMake needs to know in order to generate @@ -27,9 +27,12 @@ variable initialization only occurs if CTEST_USE_LAUNCHERS is not already defined. .. versionadded:: 3.8 - If CTEST_USE_LAUNCHERS is on in a ctest -S script + If CTEST_USE_LAUNCHERS is on in a :option:`ctest -S` script the ctest_configure command will add -DCTEST_USE_LAUNCHERS:BOOL=TRUE to the cmake command used to configure the project. + +.. TODO Use RST markup + #]=======================================================================] if(NOT DEFINED CTEST_USE_LAUNCHERS AND DEFINED ENV{CTEST_USE_LAUNCHERS_DEFAULT}) diff --git a/Modules/CheckCXXSymbolExists.cmake b/Modules/CheckCXXSymbolExists.cmake index 7b13c3a..1fa0898 100644 --- a/Modules/CheckCXXSymbolExists.cmake +++ b/Modules/CheckCXXSymbolExists.cmake @@ -74,5 +74,5 @@ include_guard(GLOBAL) include(CheckSymbolExists) macro(CHECK_CXX_SYMBOL_EXISTS SYMBOL FILES VARIABLE) - __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) + __CHECK_SYMBOL_EXISTS_IMPL(CheckSymbolExists.cxx "${SYMBOL}" "${FILES}" "${VARIABLE}" ) endmacro() diff --git a/Modules/CheckFortranFunctionExists.cmake b/Modules/CheckFortranFunctionExists.cmake index 8f1ca9d..7e3a7ee 100644 --- a/Modules/CheckFortranFunctionExists.cmake +++ b/Modules/CheckFortranFunctionExists.cmake @@ -58,8 +58,7 @@ macro(CHECK_FORTRAN_FUNCTION_EXISTS FUNCTION VARIABLE) else() set(CHECK_FUNCTION_EXISTS_ADD_LIBRARIES) endif() - file(WRITE - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f + set(__CheckFunction_testFortranCompilerSource " program TESTFortran external ${FUNCTION} @@ -68,12 +67,12 @@ macro(CHECK_FORTRAN_FUNCTION_EXISTS FUNCTION VARIABLE) " ) try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testFortranCompiler.f + SOURCE_FROM_VAR testFortranCompiler.f __CheckFunction_testFortranCompilerSource ${CHECK_FUNCTION_EXISTS_ADD_LINK_OPTIONS} ${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES} OUTPUT_VARIABLE OUTPUT ) + unset(__CheckFunction_testFortranCompilerSource) if(${VARIABLE}) set(${VARIABLE} 1 CACHE INTERNAL "Have Fortran function ${FUNCTION}") message(CHECK_PASS "found") diff --git a/Modules/CheckFunctionExists.cmake b/Modules/CheckFunctionExists.cmake index 9efa132..60f0184 100644 --- a/Modules/CheckFunctionExists.cmake +++ b/Modules/CheckFunctionExists.cmake @@ -81,17 +81,15 @@ macro(CHECK_FUNCTION_EXISTS FUNCTION VARIABLE) endif() if(CMAKE_C_COMPILER_LOADED) - set(_cfe_source ${CMAKE_ROOT}/Modules/CheckFunctionExists.c) + set(_cfe_source CheckFunctionExists.c) elseif(CMAKE_CXX_COMPILER_LOADED) - set(_cfe_source ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckFunctionExists/CheckFunctionExists.cxx) - configure_file(${CMAKE_ROOT}/Modules/CheckFunctionExists.c "${_cfe_source}" COPYONLY) + set(_cfe_source CheckFunctionExists.cxx) else() message(FATAL_ERROR "CHECK_FUNCTION_EXISTS needs either C or CXX language enabled") endif() try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - ${_cfe_source} + SOURCE_FROM_FILE "${_cfe_source}" "${CMAKE_ROOT}/Modules/CheckFunctionExists.c" COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${CHECK_FUNCTION_EXISTS_ADD_LINK_OPTIONS} ${CHECK_FUNCTION_EXISTS_ADD_LIBRARIES} diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake index cca1be9..9108e34 100644 --- a/Modules/CheckIPOSupported.cmake +++ b/Modules/CheckIPOSupported.cmake @@ -76,6 +76,23 @@ endmacro() # Run IPO/LTO test macro(_ipo_run_language_check language) + set(_C_ext "c") + set(_CXX_ext "cpp") + set(_Fortran_ext "f") + string(COMPARE EQUAL "${language}" "CUDA" is_cuda) + + set(ext ${_${language}_ext}) + if(NOT "${ext}" STREQUAL "") + set(copy_sources foo.${ext} main.${ext}) + elseif(is_cuda) + if(_CMAKE_CUDA_IPO_SUPPORTED_BY_CMAKE) + set("${X_RESULT}" YES PARENT_SCOPE) + endif() + return() + else() + message(FATAL_ERROR "Language not supported") + endif() + set(testdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/_CMakeLTOTest-${language}") file(REMOVE_RECURSE "${testdir}") @@ -100,20 +117,6 @@ macro(_ipo_run_language_check language) @ONLY ) - string(COMPARE EQUAL "${language}" "C" is_c) - string(COMPARE EQUAL "${language}" "CXX" is_cxx) - string(COMPARE EQUAL "${language}" "Fortran" is_fortran) - - if(is_c) - set(copy_sources foo.c main.c) - elseif(is_cxx) - set(copy_sources foo.cpp main.cpp) - elseif(is_fortran) - set(copy_sources foo.f main.f) - else() - message(FATAL_ERROR "Language not supported") - endif() - foreach(x ${copy_sources}) configure_file( "${try_compile_src}/${x}" @@ -134,9 +137,9 @@ macro(_ipo_run_language_check language) try_compile( _IPO_LANGUAGE_CHECK_RESULT - "${bindir}" - "${srcdir}" - "${TRY_COMPILE_PROJECT_NAME}" + PROJECT "${TRY_COMPILE_PROJECT_NAME}" + SOURCE_DIR "${srcdir}" + BINARY_DIR "${bindir}" CMAKE_FLAGS "-DCMAKE_VERBOSE_MAKEFILE=ON" "-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON" @@ -214,6 +217,11 @@ function(check_ipo_supported) list(APPEND languages "C") endif() + list(FIND enabled_languages "CUDA" result) + if(NOT result EQUAL -1) + list(APPEND languages "CUDA") + endif() + list(FIND enabled_languages "Fortran" result) if(NOT result EQUAL -1) list(APPEND languages "Fortran") @@ -222,7 +230,7 @@ function(check_ipo_supported) string(COMPARE EQUAL "${languages}" "" no_languages) if(no_languages) _ipo_not_supported( - "no C/CXX/Fortran languages found in ENABLED_LANGUAGES global property" + "no C/CXX/CUDA/Fortran languages found in ENABLED_LANGUAGES global property" ) return() endif() @@ -230,7 +238,7 @@ function(check_ipo_supported) set(languages "${X_LANGUAGES}") set(unsupported_languages "${languages}") - list(REMOVE_ITEM unsupported_languages "C" "CXX" "Fortran") + list(REMOVE_ITEM unsupported_languages "C" "CXX" "CUDA" "Fortran") string(COMPARE NOTEQUAL "${unsupported_languages}" "" has_unsupported) if(has_unsupported) _ipo_not_supported( diff --git a/Modules/CheckIncludeFile.cmake b/Modules/CheckIncludeFile.cmake index 71ddde7..4cba91b 100644 --- a/Modules/CheckIncludeFile.cmake +++ b/Modules/CheckIncludeFile.cmake @@ -54,8 +54,8 @@ macro(CHECK_INCLUDE_FILE INCLUDE VARIABLE) endif() set(MACRO_CHECK_INCLUDE_FILE_FLAGS ${CMAKE_REQUIRED_FLAGS}) set(CHECK_INCLUDE_FILE_VAR ${INCLUDE}) - configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.c.in - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.c) + file(READ ${CMAKE_ROOT}/Modules/CheckIncludeFile.c.in _CIF_SOURCE_CONTENT) + string(CONFIGURE "${_CIF_SOURCE_CONTENT}" _CIF_SOURCE_CONTENT) if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_START "Looking for ${INCLUDE}") endif() @@ -93,8 +93,7 @@ macro(CHECK_INCLUDE_FILE INCLUDE VARIABLE) endif() try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.c + SOURCE_FROM_VAR CheckIncludeFile.c _CIF_SOURCE_CONTENT COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${_CIF_LINK_OPTIONS} ${_CIF_LINK_LIBRARIES} diff --git a/Modules/CheckIncludeFileCXX.cmake b/Modules/CheckIncludeFileCXX.cmake index 953224e..f6af036 100644 --- a/Modules/CheckIncludeFileCXX.cmake +++ b/Modules/CheckIncludeFileCXX.cmake @@ -53,8 +53,8 @@ macro(CHECK_INCLUDE_FILE_CXX INCLUDE VARIABLE) endif() set(MACRO_CHECK_INCLUDE_FILE_FLAGS ${CMAKE_REQUIRED_FLAGS}) set(CHECK_INCLUDE_FILE_VAR ${INCLUDE}) - configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx) + file(READ ${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in _CIF_SOURCE_CONTENT) + string(CONFIGURE "${_CIF_SOURCE_CONTENT}" _CIF_SOURCE_CONTENT) if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_START "Looking for C++ include ${INCLUDE}") endif() @@ -92,8 +92,7 @@ macro(CHECK_INCLUDE_FILE_CXX INCLUDE VARIABLE) endif() try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx + SOURCE_FROM_VAR CheckIncludeFile.cxx _CIF_SOURCE_CONTENT COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${_CIF_LINK_OPTIONS} ${_CIF_LINK_LIBRARIES} diff --git a/Modules/CheckIncludeFiles.cmake b/Modules/CheckIncludeFiles.cmake index 1800ca8..8e82859 100644 --- a/Modules/CheckIncludeFiles.cmake +++ b/Modules/CheckIncludeFiles.cmake @@ -52,7 +52,7 @@ include_guard(GLOBAL) macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE) if(NOT DEFINED "${VARIABLE}") - set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n") + set(_src_content "/* */\n") if("x${ARGN}" STREQUAL "x") if(CMAKE_C_COMPILER_LOADED) @@ -71,9 +71,9 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE) endif() if(_lang STREQUAL "C") - set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${VARIABLE}.c) + set(src ${VARIABLE}.c) elseif(_lang STREQUAL "CXX") - set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckIncludeFiles/${VARIABLE}.cpp) + set(src ${VARIABLE}.cpp) else() message(FATAL_ERROR "Unknown language:\n ${_lang}\nSupported languages: C, CXX.\n") endif() @@ -86,13 +86,11 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE) set(CHECK_INCLUDE_FILES_CONTENT "/* */\n") set(MACRO_CHECK_INCLUDE_FILES_FLAGS ${CMAKE_REQUIRED_FLAGS}) foreach(FILE ${INCLUDE}) - string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT + string(APPEND _src_content "#include <${FILE}>\n") endforeach() - string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT + string(APPEND _src_content "\n\nint main(void){return 0;}\n") - configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" - "${src}" @ONLY) set(_INCLUDE ${INCLUDE}) # remove empty elements if("${_INCLUDE}" MATCHES "^([^;]+);.+;([^;]+)$") @@ -136,8 +134,7 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE) message(CHECK_START "Looking for ${_description}") endif() try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - ${src} + SOURCE_FROM_VAR "${src}" _src_content COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${_CIF_LINK_OPTIONS} ${_CIF_LINK_LIBRARIES} @@ -164,7 +161,7 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE) file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log "Determining if files ${INCLUDE} " "exist failed with the following output:\n" - "${OUTPUT}\nSource:\n${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") + "${OUTPUT}\nSource:\n${_src_content}\n") endif() endif() endmacro() diff --git a/Modules/CheckLibraryExists.cmake b/Modules/CheckLibraryExists.cmake index 804e0cb..56424ac 100644 --- a/Modules/CheckLibraryExists.cmake +++ b/Modules/CheckLibraryExists.cmake @@ -61,17 +61,15 @@ macro(CHECK_LIBRARY_EXISTS LIBRARY FUNCTION LOCATION VARIABLE) endif() if(CMAKE_C_COMPILER_LOADED) - set(_cle_source ${CMAKE_ROOT}/Modules/CheckFunctionExists.c) + set(_cle_source CheckFunctionExists.c) elseif(CMAKE_CXX_COMPILER_LOADED) - set(_cle_source ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckLibraryExists/CheckFunctionExists.cxx) - configure_file(${CMAKE_ROOT}/Modules/CheckFunctionExists.c "${_cle_source}" COPYONLY) + set(_cle_source CheckFunctionExists.cxx) else() message(FATAL_ERROR "CHECK_FUNCTION_EXISTS needs either C or CXX language enabled") endif() try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - ${_cle_source} + SOURCE_FROM_FILE "${_cle_source}" "${CMAKE_ROOT}/Modules/CheckFunctionExists.c" COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${CHECK_LIBRARY_EXISTS_LINK_OPTIONS} LINK_LIBRARIES ${CHECK_LIBRARY_EXISTS_LIBRARIES} diff --git a/Modules/CheckPrototypeDefinition.cmake b/Modules/CheckPrototypeDefinition.cmake index d29c5e8..12f4e86 100644 --- a/Modules/CheckPrototypeDefinition.cmake +++ b/Modules/CheckPrototypeDefinition.cmake @@ -94,14 +94,11 @@ function(check_prototype_definition _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIAB set(CHECK_PROTOTYPE_DEFINITION_PROTO ${_PROTOTYPE}) set(CHECK_PROTOTYPE_DEFINITION_RETURN ${_RETURN}) - configure_file("${__check_proto_def_dir}/CheckPrototypeDefinition.c.in" - "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c" @ONLY) - - file(READ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c _SOURCE) + file(READ ${__check_proto_def_dir}/CheckPrototypeDefinition.c.in _SOURCE) + string(CONFIGURE "${_SOURCE}" _SOURCE @ONLY) try_compile(${_VARIABLE} - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckPrototypeDefinition.c + SOURCE_FROM_VAR CheckPrototypeDefinition.c _SOURCE COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${CHECK_PROTOTYPE_DEFINITION_LINK_OPTIONS} ${CHECK_PROTOTYPE_DEFINITION_LIBS} diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake index a7139af..0d44d56 100644 --- a/Modules/CheckSymbolExists.cmake +++ b/Modules/CheckSymbolExists.cmake @@ -68,11 +68,11 @@ cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced macro(CHECK_SYMBOL_EXISTS SYMBOL FILES VARIABLE) if(CMAKE_C_COMPILER_LOADED) __CHECK_SYMBOL_EXISTS_FILTER_FLAGS(C) - __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) + __CHECK_SYMBOL_EXISTS_IMPL(CheckSymbolExists.c "${SYMBOL}" "${FILES}" "${VARIABLE}" ) __CHECK_SYMBOL_EXISTS_RESTORE_FLAGS(C) elseif(CMAKE_CXX_COMPILER_LOADED) __CHECK_SYMBOL_EXISTS_FILTER_FLAGS(CXX) - __CHECK_SYMBOL_EXISTS_IMPL("${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.cxx" "${SYMBOL}" "${FILES}" "${VARIABLE}" ) + __CHECK_SYMBOL_EXISTS_IMPL(CheckSymbolExists.cxx "${SYMBOL}" "${FILES}" "${VARIABLE}" ) __CHECK_SYMBOL_EXISTS_RESTORE_FLAGS(CXX) else() message(FATAL_ERROR "CHECK_SYMBOL_EXISTS needs either C or CXX language enabled") @@ -92,7 +92,7 @@ endmacro() macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE) if(NOT DEFINED "${VARIABLE}" OR "x${${VARIABLE}}" STREQUAL "x${VARIABLE}") - set(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n") + set(_CSE_SOURCE "/* */\n") set(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS}) if(CMAKE_REQUIRED_LINK_OPTIONS) set(CHECK_SYMBOL_EXISTS_LINK_OPTIONS @@ -113,17 +113,17 @@ macro(__CHECK_SYMBOL_EXISTS_IMPL SOURCEFILE SYMBOL FILES VARIABLE) set(CMAKE_SYMBOL_EXISTS_INCLUDES) endif() foreach(FILE ${FILES}) - string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT + string(APPEND _CSE_SOURCE "#include <${FILE}>\n") endforeach() - string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " + string(APPEND _CSE_SOURCE " int main(int argc, char** argv) { (void)argv;") set(_CSE_CHECK_NON_MACRO "return ((int*)(&${SYMBOL}))[argc];") if("${SYMBOL}" MATCHES "^[a-zA-Z_][a-zA-Z0-9_]*$") # The SYMBOL has a legal macro name. Test whether it exists as a macro. - string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " + string(APPEND _CSE_SOURCE " #ifndef ${SYMBOL} ${_CSE_CHECK_NON_MACRO} #else @@ -132,22 +132,18 @@ int main(int argc, char** argv) #endif") else() # The SYMBOL cannot be a macro (e.g., a template function). - string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " + string(APPEND _CSE_SOURCE " ${_CSE_CHECK_NON_MACRO}") endif() - string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT " + string(APPEND _CSE_SOURCE " }") unset(_CSE_CHECK_NON_MACRO) - configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" - "${SOURCEFILE}" @ONLY) - if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_START "Looking for ${SYMBOL}") endif() try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - "${SOURCEFILE}" + SOURCE_FROM_VAR "${SOURCEFILE}" _CSE_SOURCE COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${CHECK_SYMBOL_EXISTS_LINK_OPTIONS} ${CHECK_SYMBOL_EXISTS_LIBS} @@ -164,7 +160,7 @@ int main(int argc, char** argv) "Determining if the ${SYMBOL} " "exist passed with the following output:\n" "${OUTPUT}\nFile ${SOURCEFILE}:\n" - "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") + "${_CSE_SOURCE}\n") else() if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_FAIL "not found") @@ -174,9 +170,9 @@ int main(int argc, char** argv) "Determining if the ${SYMBOL} " "exist failed with the following output:\n" "${OUTPUT}\nFile ${SOURCEFILE}:\n" - "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") + "${_CSE_SOURCE}\n") endif() - unset(CMAKE_CONFIGURABLE_FILE_CONTENT) + unset(_CSE_SOURCE) endif() endmacro() diff --git a/Modules/CheckTypeSize.cmake b/Modules/CheckTypeSize.cmake index 602170c..b14ab06 100644 --- a/Modules/CheckTypeSize.cmake +++ b/Modules/CheckTypeSize.cmake @@ -104,9 +104,9 @@ function(__check_type_size_impl type var map builtin language) # Perform language check if(language STREQUAL "C") - set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.c) + set(src ${var}.c) elseif(language STREQUAL "CXX") - set(src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.cpp) + set(src ${var}.cpp) else() message(FATAL_ERROR "Unknown language:\n ${language}\nSupported languages: C, CXX.\n") endif() @@ -142,8 +142,9 @@ function(__check_type_size_impl type var map builtin language) # Perform the check. set(bin ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CheckTypeSize/${var}.bin) - configure_file(${__check_type_size_dir}/CheckTypeSize.c.in ${src} @ONLY) - try_compile(HAVE_${var} ${CMAKE_BINARY_DIR} ${src} + file(READ ${__check_type_size_dir}/CheckTypeSize.c.in src_content) + string(CONFIGURE "${src_content}" src_content @ONLY) + try_compile(HAVE_${var} SOURCE_FROM_VAR "${src}" src_content COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS} LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} @@ -209,9 +210,8 @@ function(__check_type_size_impl type var map builtin language) if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_FAIL "failed") endif() - file(READ ${src} content) file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining size of ${type} failed with the following output:\n${output}\n${src}:\n${content}\n\n") + "Determining size of ${type} failed with the following output:\n${output}\n${src}:\n${src_content}\n\n") set(${var} "" CACHE INTERNAL "CHECK_TYPE_SIZE: ${type} unknown") file(REMOVE ${map}) endif() diff --git a/Modules/CheckVariableExists.cmake b/Modules/CheckVariableExists.cmake index 7420124..5dc3441 100644 --- a/Modules/CheckVariableExists.cmake +++ b/Modules/CheckVariableExists.cmake @@ -62,8 +62,7 @@ macro(CHECK_VARIABLE_EXISTS VAR VARIABLE) set(CHECK_VARIABLE_EXISTS_ADD_LIBRARIES) endif() try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - ${CMAKE_ROOT}/Modules/CheckVariableExists.c + SOURCES ${CMAKE_ROOT}/Modules/CheckVariableExists.c COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${CHECK_VARIABLE_EXISTS_ADD_LINK_OPTIONS} ${CHECK_VARIABLE_EXISTS_ADD_LIBRARIES} diff --git a/Modules/Compiler/Clang-CUDA.cmake b/Modules/Compiler/Clang-CUDA.cmake index 219897e..d9929f1 100644 --- a/Modules/Compiler/Clang-CUDA.cmake +++ b/Modules/Compiler/Clang-CUDA.cmake @@ -35,6 +35,10 @@ set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "cudadevrt;cudart_static") set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_SHARED "cudadevrt;cudart") set(CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_NONE "") +# Clang doesn't support CUDA device LTO +set(_CMAKE_CUDA_IPO_SUPPORTED_BY_CMAKE NO) +set(_CMAKE_CUDA_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) + if(UNIX) list(APPEND CMAKE_CUDA_RUNTIME_LIBRARY_LINK_OPTIONS_STATIC "rt" "pthread" "dl") endif() diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake index df115d3..4f9af37 100644 --- a/Modules/Compiler/Clang.cmake +++ b/Modules/Compiler/Clang.cmake @@ -80,7 +80,7 @@ else() set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto") endif() - if(ANDROID AND NOT CMAKE_ANDROID_NDK_VERSION VERSION_GREATER_EQUAL "22") + if(ANDROID AND CMAKE_ANDROID_NDK_VERSION VERSION_LESS "22") # https://github.com/android-ndk/ndk/issues/242 set(CMAKE_${lang}_LINK_OPTIONS_IPO "-fuse-ld=gold") endif() @@ -255,6 +255,7 @@ macro(__compiler_clang_cxx_standards lang) cxx_std_17 cxx_std_20 cxx_std_23 + cxx_std_26 ) _record_compiler_features(${lang} "" CMAKE_${lang}_COMPILE_FEATURES) endmacro() diff --git a/Modules/Compiler/IntelLLVM-FindBinUtils.cmake b/Modules/Compiler/IntelLLVM-FindBinUtils.cmake new file mode 100644 index 0000000..c5b1ee6 --- /dev/null +++ b/Modules/Compiler/IntelLLVM-FindBinUtils.cmake @@ -0,0 +1,45 @@ +if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "") + message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set") +endif() + +# Ubuntu: +# * /usr/bin/llvm-ar-9 +# * /usr/bin/llvm-ranlib-9 +string(REGEX MATCH "^([0-9]+)" __version_x + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}") + +# Debian: +# * /usr/bin/llvm-ar-4.0 +# * /usr/bin/llvm-ranlib-4.0 +string(REGEX MATCH "^([0-9]+\\.[0-9]+)" __version_x_y + "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_VERSION}") + +# Try to find tools in the IntelLLVM Clang tools directory +get_filename_component(__intel_llvm_hint_1 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY) +get_filename_component(__intel_llvm_hint_1 "${__intel_llvm_hint_1}/../bin-llvm" REALPATH) + +get_filename_component(__intel_llvm_hint_2 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY) + +set(__intel_llvm_hints ${__intel_llvm_hint_1} ${__intel_llvm_hint_2}) + +# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ar.1.html +find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES + "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar-${__version_x_y}" + "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar-${__version_x}" + "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar" + HINTS ${__intel_llvm_hints} + NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH + DOC "LLVM archiver" +) +mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR) + +# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ranlib.1.html +find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES + "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib-${__version_x_y}" + "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib-${__version_x}" + "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib" + HINTS ${__intel_llvm_hints} + NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH + DOC "Generate index for LLVM archive" +) +mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB) diff --git a/Modules/Compiler/IntelLLVM.cmake b/Modules/Compiler/IntelLLVM.cmake index c5800dc..30de1a9 100644 --- a/Modules/Compiler/IntelLLVM.cmake +++ b/Modules/Compiler/IntelLLVM.cmake @@ -15,6 +15,15 @@ set(__pch_header_CXX "c++-header") set(__pch_header_OBJC "objective-c-header") set(__pch_header_OBJCXX "objective-c++-header") +# Variables that are common across front-end variants +macro(__compiler_intel_llvm_common lang) + set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + set(CMAKE_${lang}_ARCHIVE_CREATE_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" cr <TARGET> <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_APPEND_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" r <TARGET> <LINK_FLAGS> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_FINISH_IPO "\"${CMAKE_${lang}_COMPILER_RANLIB}\" <TARGET>") +endmacro() + if(CMAKE_HOST_WIN32) # MSVC-like macro(__compiler_intel_llvm lang) @@ -24,6 +33,9 @@ if(CMAKE_HOST_WIN32) set(CMAKE_${lang}_COMPILE_OPTIONS_INVALID_PCH -Winvalid-pch) set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX") endif() + __compiler_intel_llvm_common(${lang}) + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-Qipo") + set(CMAKE_${lang}_LINK_OPTIONS_IPO "-Qipo") endmacro() else() # GNU-like @@ -61,12 +73,9 @@ else() set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Xlinker" " ") set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP) - set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) - set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) - set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin") - set(CMAKE_${lang}_ARCHIVE_CREATE_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" cr <TARGET> <LINK_FLAGS> <OBJECTS>") - set(CMAKE_${lang}_ARCHIVE_APPEND_IPO "\"${CMAKE_${lang}_COMPILER_AR}\" r <TARGET> <LINK_FLAGS> <OBJECTS>") - set(CMAKE_${lang}_ARCHIVE_FINISH_IPO "\"${CMAKE_${lang}_COMPILER_RANLIB}\" <TARGET>") + __compiler_intel_llvm_common(${lang}) + set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-ipo") + set(CMAKE_${lang}_LINK_OPTIONS_IPO "-ipo") set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>") set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>") diff --git a/Modules/Compiler/MSVC-CXX.cmake b/Modules/Compiler/MSVC-CXX.cmake index 75165fd..60d13f1 100644 --- a/Modules/Compiler/MSVC-CXX.cmake +++ b/Modules/Compiler/MSVC-CXX.cmake @@ -72,6 +72,7 @@ elseif (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.0) cxx_std_17 cxx_std_20 cxx_std_23 + cxx_std_26 ) _record_compiler_features(CXX "" CMAKE_CXX_COMPILE_FEATURES) endmacro() diff --git a/Modules/Compiler/NVIDIA-CUDA.cmake b/Modules/Compiler/NVIDIA-CUDA.cmake index e07d152..c8dcd2a 100644 --- a/Modules/Compiler/NVIDIA-CUDA.cmake +++ b/Modules/Compiler/NVIDIA-CUDA.cmake @@ -48,6 +48,13 @@ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) set(CMAKE_CUDA_DEPENDS_USE_COMPILER TRUE) endif() +if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.2) + set(_CMAKE_CUDA_IPO_SUPPORTED_BY_CMAKE YES) + set(_CMAKE_CUDA_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + + set(CMAKE_CUDA_DEVICE_LINK_OPTIONS_IPO " -dlto") +endif() + if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") set(CMAKE_CUDA_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE) set(CMAKE_CUDA_COMPILE_OPTIONS_PIC -Xcompiler=-fPIC) @@ -61,6 +68,7 @@ if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC") string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -O1 -DNDEBUG") string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG") endif() + set(CMAKE_SHARED_LIBRARY_CREATE_CUDA_FLAGS -shared) set(CMAKE_INCLUDE_SYSTEM_FLAG_CUDA -isystem=) @@ -132,15 +140,19 @@ else() endif() -# FIXME: investigate use of --options-file. -# Tell Makefile generator that nvcc does not support @<rspfile> syntax. -set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0) -set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0) -set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0) - if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "9.0") set(CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG "--options-file ") set(CMAKE_CUDA_RESPONSE_FILE_FLAG "--options-file ") endif() +if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0") + set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 1) + set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 1) + set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 1) +else() + set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES 0) + set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES 0) + set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS 0) +endif() + __compiler_check_default_language_standard(CUDA 6.0 03) diff --git a/Modules/Compiler/Tasking-ASM.cmake b/Modules/Compiler/Tasking-ASM.cmake new file mode 100644 index 0000000..19bce19 --- /dev/null +++ b/Modules/Compiler/Tasking-ASM.cmake @@ -0,0 +1,7 @@ +include(Compiler/Tasking) + +set(CMAKE_ASM_OUTPUT_EXTENSION ".o") +set(CMAKE_ASM_OUTPUT_EXTENSION_REPLACE 1) + +set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>") +set(CMAKE_ASM_SOURCE_FILE_EXTENSIONS S;s;asm;msa) diff --git a/Modules/Compiler/Tasking-C.cmake b/Modules/Compiler/Tasking-C.cmake new file mode 100644 index 0000000..0ea3cd2 --- /dev/null +++ b/Modules/Compiler/Tasking-C.cmake @@ -0,0 +1,47 @@ +include(Compiler/Tasking) +__compiler_tasking(C) + +set(CMAKE_C90_STANDARD_COMPILE_OPTION "--iso=90" "--strict") +set(CMAKE_C90_EXTENSION_COMPILE_OPTION "--iso=90" " ") + +set(CMAKE_C99_STANDARD_COMPILE_OPTION "--iso=99" "--strict") +set(CMAKE_C99_EXTENSION_COMPILE_OPTION "--iso=99" " ") + +set(CMAKE_C11_STANDARD_COMPILE_OPTION "--iso=11" "--strict") +set(CMAKE_C11_EXTENSION_COMPILE_OPTION "--iso=11" " ") + +if(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "TriCore") + if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode") + __compiler_check_default_language_standard(C 10.1 11) + else() + __compiler_check_default_language_standard(C 6.3 11) + endif() +elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "ARM") + if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode") + __compiler_check_default_language_standard(C 10.1 11) + elseif(CMAKE_TASKING_TOOLSET STREQUAL "TriCore") + __compiler_check_default_language_standard(C 6.3 11) + else() + __compiler_check_default_language_standard(C 6.0 11) + endif() +elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "MCS") + if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode") + __compiler_check_default_language_standard(C 10.1 11) + elseif(CMAKE_TASKING_TOOLSET STREQUAL "TriCore") + __compiler_check_default_language_standard(C 6.3 11) + else() + __compiler_check_default_language_standard(C 3.3 11) + endif() +elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "ARC") + __compiler_check_default_language_standard(C 10.1 11) +elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "8051") + if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode") + __compiler_check_default_language_standard(C 10.1 11) + elseif(CMAKE_TASKING_TOOLSET STREQUAL "TriCore") + __compiler_check_default_language_standard(C 6.3 11) + else() + __compiler_check_default_language_standard(C 7.2 89) + endif() +elseif(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "PCP") + __compiler_check_default_language_standard(C 6.3 11) +endif() diff --git a/Modules/Compiler/Tasking-CXX.cmake b/Modules/Compiler/Tasking-CXX.cmake new file mode 100644 index 0000000..635104c --- /dev/null +++ b/Modules/Compiler/Tasking-CXX.cmake @@ -0,0 +1,31 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. +include(Compiler/Tasking) +__compiler_tasking(CXX) + +set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "--c++=03" "--strict") +set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "--iso=03" " ") + +set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "--c++=11" "--strict") +set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "--c++=11" " ") + +set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "--c++=14" "--strict") +set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "--c++=14" " ") + +if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "TriCore") + if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode") + __compiler_check_default_language_standard(CXX 10.1 14) + else() + __compiler_check_default_language_standard(CXX 6.3 14) + endif() +elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "ARM") + if(CMAKE_TASKING_TOOLSET STREQUAL "SmartCode") + __compiler_check_default_language_standard(CXX 10.1 14) + elseif(CMAKE_TASKING_TOOLSET STREQUAL "TriCore") + __compiler_check_default_language_standard(CXX 6.3 14) + else() + __compiler_check_default_language_standard(CXX 6.0 14) + endif() +else() + message(FATAL_ERROR "CXX is not supported with the ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} architecture.") +endif() diff --git a/Modules/Compiler/Tasking-DetermineCompiler.cmake b/Modules/Compiler/Tasking-DetermineCompiler.cmake new file mode 100644 index 0000000..a40be19 --- /dev/null +++ b/Modules/Compiler/Tasking-DetermineCompiler.cmake @@ -0,0 +1,10 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. +set(_compiler_id_pp_test "defined(__TASKING__)") + +set(_compiler_id_version_compute " + # define @PREFIX@COMPILER_VERSION_MAJOR @MACRO_DEC@(__VERSION__/1000) + # define @PREFIX@COMPILER_VERSION_MINOR @MACRO_DEC@(__VERSION__ % 100)") + +string(APPEND _compiler_id_version_compute " +# define @PREFIX@COMPILER_VERSION_INTERNAL @MACRO_DEC@(__VERSION__)") diff --git a/Modules/Compiler/Tasking-FindBinUtils.cmake b/Modules/Compiler/Tasking-FindBinUtils.cmake new file mode 100644 index 0000000..eab31d7 --- /dev/null +++ b/Modules/Compiler/Tasking-FindBinUtils.cmake @@ -0,0 +1,18 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# Find the archiver for the compiler architecture, which is always in the same +# directory as the compiler. +if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "") + message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set") +endif() + +get_filename_component(__tasking_hints "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY) + +find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR + NAMES artc ararm armcs ar51 ararc arpcp + HINTS ${__tasking_hints} + NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH + DOC "Tasking Archiver" +) +mark_as_advanced(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR) diff --git a/Modules/Compiler/Tasking.cmake b/Modules/Compiler/Tasking.cmake new file mode 100644 index 0000000..d0c2f79 --- /dev/null +++ b/Modules/Compiler/Tasking.cmake @@ -0,0 +1,86 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# This module is shared by multiple languages; use include blocker. +if(_Tasking_CMAKE_LOADED) + return() +endif() +set(_Tasking_CMAKE_LOADED TRUE) +include(Compiler/CMakeCommonCompilerMacros) + +set(CMAKE_EXECUTABLE_SUFFIX ".elf") +set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE) +set(BUILD_SHARED_LIBS FALSE CACHE BOOL "") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") +set(CMAKE_LINK_SEARCH_START_STATIC TRUE) + +function(__tasking_set_processor_list lang out_var) + execute_process(COMMAND "${CMAKE_${lang}_COMPILER}" --cpu-list + OUTPUT_VARIABLE processor_list + ERROR_VARIABLE processor_list) + string(REGEX MATCHALL " +([A-Za-z0-9_]+)[^\n]+\n" processor_list "${processor_list}") + list(POP_FRONT processor_list) + string(REGEX REPLACE " +([A-Za-z0-9_]+)[^\n]+\n" "\\1" processor_list "${processor_list}") + set(${out_var} "${processor_list}" PARENT_SCOPE) +endfunction() + +function(__tasking_check_processor processor list out_var) + string(TOLOWER "${processor}" processor) + if(processor IN_LIST list) + set(${out_var} TRUE PARENT_SCOPE) + else() + set(${out_var} FALSE PARENT_SCOPE) + endif() +endfunction() + +if(NOT CMAKE_TASKING_TOOLSET) + set(CMAKE_TASKING_TOOLSET "Standalone") +endif() + +macro(__compiler_tasking lang) + + if(CMAKE_SYSTEM_PROCESSOR) + if(NOT _TASKING_${lang}_PROCESSOR_LIST) + __tasking_set_processor_list(${lang} _TASKING_${lang}_PROCESSOR_LIST) + endif() + __tasking_check_processor(${CMAKE_SYSTEM_PROCESSOR} "${_TASKING_${lang}_PROCESSOR_LIST}" _TASKING_${lang}_VALID_PROCESSOR) + if(${_TASKING_${lang}_VALID_PROCESSOR}) + string(APPEND CMAKE_${lang}_FLAGS_INIT " -C${CMAKE_SYSTEM_PROCESSOR}") + else() + message(FATAL_ERROR "Invalid processor ${CMAKE_SYSTEM_PROCESSOR} specified.\n" + "Supported processors: ${_TASKING_${lang}_PROCESSOR_LIST}") + endif() + endif() + + set(CMAKE_${lang}_VERBOSE_FLAG "-v") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl" " ") + set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "-f ") + set(CMAKE_DEPFILE_FLAGS_${lang} "--dep-file=<DEP_FILE>") + set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "--warning-as-errors") + + string(APPEND CMAKE_${lang}_FLAGS_INIT " ") + string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -O0 -g") + string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -O2 -t4 -DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O2 -t2 -DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -t2 -g -DNDEBUG") + + set(CMAKE_${lang}_ARCHIVE_CREATE "\"${CMAKE_${lang}_COMPILER_AR}\" -r <TARGET> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_APPEND "\"${CMAKE_${lang}_COMPILER_AR}\" -r <TARGET> <OBJECTS>") + set(CMAKE_${lang}_ARCHIVE_FINISH "") + + set(CMAKE_${lang}_CREATE_ASSEMBLY_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -cs <SOURCE> -o <ASSEMBLY_SOURCE>") + set(CMAKE_${lang}_CREATE_PREPROCESSED_SOURCE "<CMAKE_${lang}_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -Ep <SOURCE> > <PREPROCESSED_SOURCE>") + + set(CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "${CMAKE_${lang}_COMPILER}") + if(CMAKE_${lang}_COMPILER_ARG1) + separate_arguments(_COMPILER_ARGS NATIVE_COMMAND "${CMAKE_${lang}_COMPILER_ARG1}") + list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND ${_COMPILER_ARGS}) + unset(_COMPILER_ARGS) + endif() + list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-Ep" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp") + +endmacro() diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 9952658..22a25bd 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -1840,7 +1840,11 @@ function(_ep_get_build_command else() set(cmd "${CMAKE_COMMAND}") endif() - set(args --build ".") + if(step STREQUAL "INSTALL") + set(args --install ".") + else() + set(args --build ".") + endif() get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(_isMultiConfig) if (CMAKE_CFG_INTDIR AND @@ -1862,9 +1866,6 @@ function(_ep_get_build_command endif() list(APPEND args --config ${config}) endif() - if(step STREQUAL "INSTALL") - list(APPEND args --target install) - endif() # But for "TEST" drive the project with corresponding "ctest". if("x${step}x" STREQUAL "xTESTx") string(REGEX REPLACE "^(.*/)cmake([^/]*)$" "\\1ctest\\2" cmd "${cmd}") @@ -3832,6 +3833,19 @@ function(_ep_add_install_command name) set(uses_terminal "") endif() + # With BUILD_ALWAYS+BUILD_BYPRODUCTS, Ninja restats the + # build step outputs and may not consider this step to + # be out-of-date. Explicitly mark it out-of-date too. + get_property(build_always + TARGET ${name} + PROPERTY _EP_BUILD_ALWAYS + ) + if(build_always) + set(always 1) + else() + set(always 0) + endif() + set(__cmdQuoted) foreach(__item IN LISTS cmd) string(APPEND __cmdQuoted " [==[${__item}]==]") @@ -3842,6 +3856,7 @@ function(_ep_add_install_command name) COMMAND ${__cmdQuoted} WORKING_DIRECTORY \${binary_dir} DEPENDEES build + ALWAYS \${always} ${log} ${uses_terminal} )" diff --git a/Modules/ExternalProject/gitupdate.cmake.in b/Modules/ExternalProject/gitupdate.cmake.in index 7896f62..50f0167 100644 --- a/Modules/ExternalProject/gitupdate.cmake.in +++ b/Modules/ExternalProject/gitupdate.cmake.in @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.5) function(get_hash_for_ref ref out_var err_var) execute_process( - COMMAND "@git_EXECUTABLE@" rev-parse "${ref}^0" + COMMAND "@git_EXECUTABLE@" --git-dir=.git rev-parse "${ref}^0" WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code OUTPUT_VARIABLE ref_hash @@ -27,7 +27,7 @@ endif() execute_process( - COMMAND "@git_EXECUTABLE@" show-ref "@git_tag@" + COMMAND "@git_EXECUTABLE@" --git-dir=.git show-ref "@git_tag@" WORKING_DIRECTORY "@work_dir@" OUTPUT_VARIABLE show_ref_output ) @@ -95,7 +95,7 @@ endif() if(fetch_required) message(VERBOSE "Fetching latest from the remote @git_remote_name@") execute_process( - COMMAND "@git_EXECUTABLE@" fetch --tags --force "@git_remote_name@" + COMMAND "@git_EXECUTABLE@" --git-dir=.git fetch --tags --force "@git_remote_name@" WORKING_DIRECTORY "@work_dir@" COMMAND_ERROR_IS_FATAL ANY ) @@ -112,7 +112,7 @@ if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$") # We can't if we aren't already on a branch and we shouldn't if that local # branch isn't tracking the one we want to checkout. execute_process( - COMMAND "@git_EXECUTABLE@" symbolic-ref -q HEAD + COMMAND "@git_EXECUTABLE@" --git-dir=.git symbolic-ref -q HEAD WORKING_DIRECTORY "@work_dir@" OUTPUT_VARIABLE current_branch OUTPUT_STRIP_TRAILING_WHITESPACE @@ -128,7 +128,7 @@ if(git_update_strategy MATCHES "^REBASE(_CHECKOUT)?$") else() execute_process( - COMMAND "@git_EXECUTABLE@" for-each-ref "--format=%(upstream:short)" "${current_branch}" + COMMAND "@git_EXECUTABLE@" --git-dir=.git for-each-ref "--format=%(upstream:short)" "${current_branch}" WORKING_DIRECTORY "@work_dir@" OUTPUT_VARIABLE upstream_branch OUTPUT_STRIP_TRAILING_WHITESPACE @@ -151,7 +151,7 @@ endif() # Check if stash is needed execute_process( - COMMAND "@git_EXECUTABLE@" status --porcelain + COMMAND "@git_EXECUTABLE@" --git-dir=.git status --porcelain WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code OUTPUT_VARIABLE repo_status @@ -165,7 +165,7 @@ string(LENGTH "${repo_status}" need_stash) # rebase or checkout without losing those changes permanently if(need_stash) execute_process( - COMMAND "@git_EXECUTABLE@" stash save @git_stash_save_options@ + COMMAND "@git_EXECUTABLE@" --git-dir=.git stash save @git_stash_save_options@ WORKING_DIRECTORY "@work_dir@" COMMAND_ERROR_IS_FATAL ANY ) @@ -173,13 +173,13 @@ endif() if(git_update_strategy STREQUAL "CHECKOUT") execute_process( - COMMAND "@git_EXECUTABLE@" checkout "${checkout_name}" + COMMAND "@git_EXECUTABLE@" --git-dir=.git checkout "${checkout_name}" WORKING_DIRECTORY "@work_dir@" COMMAND_ERROR_IS_FATAL ANY ) else() execute_process( - COMMAND "@git_EXECUTABLE@" rebase "${checkout_name}" + COMMAND "@git_EXECUTABLE@" --git-dir=.git rebase "${checkout_name}" WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code OUTPUT_VARIABLE rebase_output @@ -188,7 +188,7 @@ else() if(error_code) # Rebase failed, undo the rebase attempt before continuing execute_process( - COMMAND "@git_EXECUTABLE@" rebase --abort + COMMAND "@git_EXECUTABLE@" --git-dir=.git rebase --abort WORKING_DIRECTORY "@work_dir@" ) @@ -196,7 +196,7 @@ else() # Not allowed to do a checkout as a fallback, so cannot proceed if(need_stash) execute_process( - COMMAND "@git_EXECUTABLE@" stash pop --index --quiet + COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet WORKING_DIRECTORY "@work_dir@" ) endif() @@ -218,7 +218,7 @@ else() message(WARNING "Rebase failed, output has been saved to ${error_log_file}" "\nFalling back to checkout, previous commit tagged as ${tag_name}") execute_process( - COMMAND "@git_EXECUTABLE@" tag -a + COMMAND "@git_EXECUTABLE@" --git-dir=.git tag -a -m "ExternalProject attempting to move from here to ${checkout_name}" ${tag_name} WORKING_DIRECTORY "@work_dir@" @@ -226,7 +226,7 @@ else() ) execute_process( - COMMAND "@git_EXECUTABLE@" checkout "${checkout_name}" + COMMAND "@git_EXECUTABLE@" --git-dir=.git checkout "${checkout_name}" WORKING_DIRECTORY "@work_dir@" COMMAND_ERROR_IS_FATAL ANY ) @@ -236,29 +236,29 @@ endif() if(need_stash) # Put back the stashed changes execute_process( - COMMAND "@git_EXECUTABLE@" stash pop --index --quiet + COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code ) if(error_code) # Stash pop --index failed: Try again dropping the index execute_process( - COMMAND "@git_EXECUTABLE@" reset --hard --quiet + COMMAND "@git_EXECUTABLE@" --git-dir=.git reset --hard --quiet WORKING_DIRECTORY "@work_dir@" ) execute_process( - COMMAND "@git_EXECUTABLE@" stash pop --quiet + COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --quiet WORKING_DIRECTORY "@work_dir@" RESULT_VARIABLE error_code ) if(error_code) # Stash pop failed: Restore previous state. execute_process( - COMMAND "@git_EXECUTABLE@" reset --hard --quiet ${head_sha} + COMMAND "@git_EXECUTABLE@" --git-dir=.git reset --hard --quiet ${head_sha} WORKING_DIRECTORY "@work_dir@" ) execute_process( - COMMAND "@git_EXECUTABLE@" stash pop --index --quiet + COMMAND "@git_EXECUTABLE@" --git-dir=.git stash pop --index --quiet WORKING_DIRECTORY "@work_dir@" ) message(FATAL_ERROR "\nFailed to unstash changes in: '@work_dir@'." @@ -270,7 +270,7 @@ endif() set(init_submodules "@init_submodules@") if(init_submodules) execute_process( - COMMAND "@git_EXECUTABLE@" submodule update @git_submodules_recurse@ --init @git_submodules@ + COMMAND "@git_EXECUTABLE@" --git-dir=.git submodule update @git_submodules_recurse@ --init @git_submodules@ WORKING_DIRECTORY "@work_dir@" COMMAND_ERROR_IS_FATAL ANY ) diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 995e69a..ac3918c 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -111,6 +111,7 @@ Commands FetchContent_Declare( <name> <contentOptions>... + [SYSTEM] [OVERRIDE_FIND_PACKAGE | FIND_PACKAGE_ARGS args...] ) @@ -229,6 +230,16 @@ Commands to intercept any direct call to :command:`find_package`, except if that call contains the ``BYPASS_PROVIDER`` option. + .. versionadded:: 3.25 + + ``SYSTEM`` + If the ``SYSTEM`` argument is provided, targets created by + the dependency will have their :prop_tgt:`SYSTEM` property + set to true when populated by :command:`FetchContent_MakeAvailable`. + The entries in their :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` + will be treated as ``SYSTEM`` include directories when + compiling consumers. + .. command:: FetchContent_MakeAvailable .. versionadded:: 3.14 @@ -884,9 +895,10 @@ Overriding Where To Find CMakeLists.txt If the sub-project's ``CMakeLists.txt`` file is not at the top level of its source tree, the ``SOURCE_SUBDIR`` option can be used to tell ``FetchContent`` -where to find it. The following example shows how to use that option and +where to find it. The following example shows how to use that option, and it also sets a variable which is meaningful to the subproject before pulling -it into the main build: +it into the main build (set as an ``INTERNAL`` cache variable to avoid +problems with policy :policy:`CMP0077`): .. code-block:: cmake @@ -897,7 +909,7 @@ it into the main build: GIT_TAG ae50d9b9902526efd6c7a1907d09739f959c6297 # v3.15.0 SOURCE_SUBDIR cmake ) - set(protobuf_BUILD_TESTS OFF) + set(protobuf_BUILD_TESTS OFF CACHE INTERNAL "") FetchContent_MakeAvailable(protobuf) Complex Dependency Hierarchies @@ -1972,13 +1984,17 @@ macro(FetchContent_MakeAvailable) if("${__cmake_contentDetails}" STREQUAL "") message(FATAL_ERROR "No details have been set for content: ${__cmake_contentName}") endif() - cmake_parse_arguments(__cmake_arg "" "SOURCE_SUBDIR" "" ${__cmake_contentDetails}) + cmake_parse_arguments(__cmake_arg "SYSTEM" "SOURCE_SUBDIR" "" ${__cmake_contentDetails}) if(NOT "${__cmake_arg_SOURCE_SUBDIR}" STREQUAL "") string(APPEND __cmake_srcdir "/${__cmake_arg_SOURCE_SUBDIR}") endif() if(EXISTS ${__cmake_srcdir}/CMakeLists.txt) - add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR}) + if (__cmake_arg_SYSTEM) + add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR} SYSTEM) + else() + add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR}) + endif() endif() unset(__cmake_srcdir) diff --git a/Modules/FindBLAS.cmake b/Modules/FindBLAS.cmake index 7a381af..d02c589 100644 --- a/Modules/FindBLAS.cmake +++ b/Modules/FindBLAS.cmake @@ -35,6 +35,12 @@ The following variables may be set to influence this module's behavior: if set ``pkg-config`` will be used to search for a BLAS library first and if one is found that is preferred +``BLA_PKGCONFIG_BLAS`` + .. versionadded:: 3.25 + + If set, the ``pkg-config`` method will look for this module name instead of + just ``blas``. + ``BLA_SIZEOF_INTEGER`` .. versionadded:: 3.22 @@ -273,8 +279,11 @@ endif() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) if(BLA_PREFER_PKGCONFIG) + if(NOT BLA_PKGCONFIG_BLAS) + set(BLA_PKGCONFIG_BLAS "blas") + endif() find_package(PkgConfig QUIET) - pkg_check_modules(PKGC_BLAS QUIET blas) + pkg_check_modules(PKGC_BLAS QUIET ${BLA_PKGCONFIG_BLAS}) if(PKGC_BLAS_FOUND) set(BLAS_FOUND ${PKGC_BLAS_FOUND}) set(BLAS_LIBRARIES "${PKGC_BLAS_LINK_LIBRARIES}") diff --git a/Modules/FindCUDA.cmake b/Modules/FindCUDA.cmake index af5f798..470111f 100644 --- a/Modules/FindCUDA.cmake +++ b/Modules/FindCUDA.cmake @@ -799,7 +799,9 @@ if(NOT "${CUDA_TOOLKIT_ROOT_DIR}" STREQUAL "${CUDA_TOOLKIT_ROOT_DIR_INTERNAL}") unset(CUDA_VERSION CACHE) endif() -if(NOT "${CUDA_TOOLKIT_TARGET_DIR}" STREQUAL "${CUDA_TOOLKIT_TARGET_DIR_INTERNAL}") +# If CUDA_TOOLKIT_TARGET_DIR exists, check if it has changed. +if(DEFINED CUDA_TOOLKIT_TARGET_DIR + AND NOT "${CUDA_TOOLKIT_TARGET_DIR}" STREQUAL "${CUDA_TOOLKIT_TARGET_DIR_INTERNAL}") cuda_unset_include_and_libraries() endif() diff --git a/Modules/FindCUDA/select_compute_arch.cmake b/Modules/FindCUDA/select_compute_arch.cmake index a35b3f8..5fad337 100644 --- a/Modules/FindCUDA/select_compute_arch.cmake +++ b/Modules/FindCUDA/select_compute_arch.cmake @@ -135,10 +135,10 @@ function(CUDA_DETECT_INSTALLED_GPUS OUT_VARIABLE) "}\n") if(CMAKE_CUDA_COMPILER_LOADED) # CUDA as a language - try_run(run_result compile_result ${PROJECT_BINARY_DIR} ${file} + try_run(run_result compile_result SOURCES ${file} RUN_OUTPUT_VARIABLE compute_capabilities) else() - try_run(run_result compile_result ${PROJECT_BINARY_DIR} ${file} + try_run(run_result compile_result SOURCES ${file} CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CUDA_INCLUDE_DIRS}" LINK_LIBRARIES ${CUDA_LIBRARIES} RUN_OUTPUT_VARIABLE compute_capabilities) diff --git a/Modules/FindCUDAToolkit.cmake b/Modules/FindCUDAToolkit.cmake index 5f83ccc..7699e28 100644 --- a/Modules/FindCUDAToolkit.cmake +++ b/Modules/FindCUDAToolkit.cmake @@ -109,6 +109,7 @@ of the following libraries that are part of the CUDAToolkit: - :ref:`CUDA Runtime Library<cuda_toolkit_rt_lib>` - :ref:`CUDA Driver Library<cuda_toolkit_driver_lib>` - :ref:`cuBLAS<cuda_toolkit_cuBLAS>` +- :ref:`cuFile<cuda_toolkit_cuFile>` - :ref:`cuFFT<cuda_toolkit_cuFFT>` - :ref:`cuRAND<cuda_toolkit_cuRAND>` - :ref:`cuSOLVER<cuda_toolkit_cuSOLVER>` @@ -119,8 +120,10 @@ of the following libraries that are part of the CUDAToolkit: - :ref:`nvGRAPH<cuda_toolkit_nvGRAPH>` - :ref:`nvJPEG<cuda_toolkit_nvJPEG>` - :ref:`nvidia-ML<cuda_toolkit_nvML>` +- :ref:`nvPTX Compiler<cuda_toolkit_nvptx>` - :ref:`nvRTC<cuda_toolkit_nvRTC>` - :ref:`nvToolsExt<cuda_toolkit_nvToolsExt>` +- :ref:`nvtx3<cuda_toolkit_nvtx3>` - :ref:`OpenCL<cuda_toolkit_opencl>` - :ref:`cuLIBOS<cuda_toolkit_cuLIBOS>` @@ -163,6 +166,22 @@ Targets Created: - ``CUDA::cublasLt`` starting in CUDA 10.1 - ``CUDA::cublasLt_static`` starting in CUDA 10.1 +.. _`cuda_toolkit_cuFile`: + +cuFile +"""""" + +.. versionadded:: 3.25 + +The NVIDIA GPUDirect Storage `cuFile <https://docs.nvidia.com/cuda/cufile-api/index.html>`_ library. + +Targets Created: + +- ``CUDA::cuFile`` starting in CUDA 11.4 +- ``CUDA::cuFile_static`` starting in CUDA 11.4 +- ``CUDA::cuFile_rdma`` starting in CUDA 11.4 +- ``CUDA::cuFile_rdma_static`` starting in CUDA 11.4 + .. _`cuda_toolkit_cuFFT`: cuFFT @@ -333,6 +352,22 @@ Targets Created: - ``CUDA::nvjpeg`` - ``CUDA::nvjpeg_static`` +.. _`cuda_toolkit_nvPTX`: + +nvPTX Compiler +"""""""""""""" + +.. versionadded:: 3.25 + +The `nvPTX <https://docs.nvidia.com/cuda/ptx-compiler-api/index.html>`_ (PTX Compilation) library. +The PTX Compiler APIs are a set of APIs which can be used to compile a PTX program into GPU assembly code. +Introduced in CUDA 11.1 +This is a static library only. + +Targets Created: + +- ``CUDA::nvptxcompiler`` starting in CUDA 11.1 + .. _`cuda_toolkit_nvRTC`: nvRTC @@ -362,6 +397,8 @@ Targets Created: nvToolsExt """""""""" +.. deprecated:: 3.25 With CUDA 10.0+, use :ref:`nvtx3 <cuda_toolkit_nvtx3>`. + The `NVIDIA Tools Extension <https://docs.nvidia.com/gameworks/content/gameworkslibrary/nvtx/nvidia_tools_extension_library_nvtx.htm>`_. This is a shared library only. @@ -369,6 +406,20 @@ Targets Created: - ``CUDA::nvToolsExt`` +.. _`cuda_toolkit_nvtx3`: + +nvtx3 +""""" + +.. versionadded:: 3.25 + +The header-only `NVIDIA Tools Extension Library <https://nvidia.github.io/NVTX/doxygen/index.html>`_. +Introduced in CUDA 10.0. + +Targets created: + +- ``CUDA::nvtx3`` + .. _`cuda_toolkit_opencl`: OpenCL @@ -942,6 +993,14 @@ if(CUDAToolkit_FOUND) _CUDAToolkit_find_and_add_import_lib(cublas_static DEPS culibos) endif() + if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 11.4) + _CUDAToolkit_find_and_add_import_lib(cuFile DEPS culibos) + _CUDAToolkit_find_and_add_import_lib(cuFile_static DEPS culibos) + + _CUDAToolkit_find_and_add_import_lib(cuFile_rdma DEPS cuFile culibos) + _CUDAToolkit_find_and_add_import_lib(cuFile_rdma_static DEPS cuFile_static culibos) + endif() + # cuFFTW depends on cuFFT _CUDAToolkit_find_and_add_import_lib(cufftw DEPS cufft) _CUDAToolkit_find_and_add_import_lib(cufftw_static DEPS cufft_static) @@ -998,6 +1057,9 @@ if(CUDAToolkit_FOUND) endif() _CUDAToolkit_find_and_add_import_lib(nvrtc DEPS cuda_driver) + if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 11.1.0) + _CUDAToolkit_find_and_add_import_lib(nvptxcompiler_static DEPS cuda_driver) + endif() _CUDAToolkit_find_and_add_import_lib(nvml ALT nvidia-ml nvml) @@ -1014,6 +1076,21 @@ if(CUDAToolkit_FOUND) endif() _CUDAToolkit_find_and_add_import_lib(nvToolsExt ALT nvToolsExt64) + if(CUDAToolkit_VERSION VERSION_GREATER_EQUAL 10.0) + # nvToolsExt is deprecated since nvtx3 introduction. + # Warn only if the project requires a sufficiently new CMake to make migration possible. + if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_GREATER_EQUAL 3.25) + set_property(TARGET CUDA::nvToolsExt PROPERTY DEPRECATION "nvToolsExt has been superseded by nvtx3 since CUDA 10.0 and CMake 3.25. Use CUDA::nvtx3 and include <nvtx3/nvToolsExt.h> instead.") + endif() + + # Header-only variant. Uses dlopen(). + if(NOT TARGET CUDA::nvtx3) + add_library(CUDA::nvtx3 INTERFACE IMPORTED) + target_include_directories(CUDA::nvtx3 SYSTEM INTERFACE "${CUDAToolkit_INCLUDE_DIRS}") + target_link_libraries(CUDA::nvtx3 INTERFACE ${CMAKE_DL_LIBS}) + endif() + endif() + _CUDAToolkit_find_and_add_import_lib(OpenCL) endif() diff --git a/Modules/FindCURL.cmake b/Modules/FindCURL.cmake index e37d225..acb87dc 100644 --- a/Modules/FindCURL.cmake +++ b/Modules/FindCURL.cmake @@ -72,6 +72,8 @@ if(NOT CURL_NO_CURL_CMAKE) # can print what we found and return. if(CURL_FOUND) find_package_handle_standard_args(CURL HANDLE_COMPONENTS CONFIG_MODE) + # The upstream curl package sets CURL_VERSION, not CURL_VERSION_STRING. + set(CURL_VERSION_STRING "${CURL_VERSION}") return() endif() endif() @@ -80,7 +82,6 @@ find_package(PkgConfig QUIET) if(PKG_CONFIG_FOUND) pkg_check_modules(PC_CURL QUIET libcurl) if(PC_CURL_FOUND) - set(CURL_VERSION_STRING ${PC_CURL_VERSION}) pkg_get_variable(CURL_SUPPORTED_PROTOCOLS libcurl supported_protocols) pkg_get_variable(CURL_SUPPORTED_FEATURES libcurl supported_features) endif() @@ -120,7 +121,7 @@ if(NOT CURL_LIBRARY) select_library_configurations(CURL) endif() -if(CURL_INCLUDE_DIR AND NOT CURL_VERSION_STRING) +if(CURL_INCLUDE_DIR) foreach(_curl_version_header curlver.h curl.h) if(EXISTS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}") file(STRINGS "${CURL_INCLUDE_DIR}/curl/${_curl_version_header}" curl_version_str REGEX "^#define[\t ]+LIBCURL_VERSION[\t ]+\".*\"") diff --git a/Modules/FindCoin3D.cmake b/Modules/FindCoin3D.cmake index 301e70b..5910ad1 100644 --- a/Modules/FindCoin3D.cmake +++ b/Modules/FindCoin3D.cmake @@ -31,11 +31,11 @@ if (WIN32) "[HKEY_LOCAL_MACHINE\\SOFTWARE\\SIM\\Coin3D\\2;Installation Path]/include" ) - find_library(COIN3D_LIBRARY_DEBUG coin2d + find_library(COIN3D_LIBRARY_DEBUG NAMES coin2d coin4d "[HKEY_LOCAL_MACHINE\\SOFTWARE\\SIM\\Coin3D\\2;Installation Path]/lib" ) - find_library(COIN3D_LIBRARY_RELEASE coin2 + find_library(COIN3D_LIBRARY_RELEASE NAMES coin2 coin4 "[HKEY_LOCAL_MACHINE\\SOFTWARE\\SIM\\Coin3D\\2;Installation Path]/lib" ) diff --git a/Modules/FindDoxygen.cmake b/Modules/FindDoxygen.cmake index 4a16e31..23b7107 100644 --- a/Modules/FindDoxygen.cmake +++ b/Modules/FindDoxygen.cmake @@ -432,9 +432,44 @@ endif() # or use something like homebrew. # ============== End OSX stuff ================ +include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) + # # Find Doxygen... # +function(_Doxygen_get_version doxy_version result_var doxy_path) + execute_process( + COMMAND "${doxy_path}" --version + OUTPUT_VARIABLE full_doxygen_version + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE version_result + ) + + # Ignore any commit hashes, etc. + string(REGEX MATCH [[^[0-9]+\.[0-9]+\.[0-9]+]] sem_doxygen_version "${full_doxygen_version}") + + set(${result_var} ${version_result} PARENT_SCOPE) + set(${doxy_version} ${sem_doxygen_version} PARENT_SCOPE) +endfunction() + +function(_Doxygen_version_validator version_match doxy_path) + if(NOT DEFINED Doxygen_FIND_VERSION) + set(${is_valid_version} TRUE PARENT_SCOPE) + else() + _Doxygen_get_version(candidate_version version_result "${doxy_path}") + + if(version_result) + message(DEBUG "Unable to determine candidate doxygen version at ${doxy_path}: ${version_result}") + endif() + + find_package_check_version("${candidate_version}" valid_doxy_version + HANDLE_VERSION_RANGE + ) + + set(${version_match} "${valid_doxy_version}" PARENT_SCOPE) + endif() +endfunction() + macro(_Doxygen_find_doxygen) find_program( DOXYGEN_EXECUTABLE @@ -446,16 +481,13 @@ macro(_Doxygen_find_doxygen) /Applications/Utilities/Doxygen.app/Contents/Resources /Applications/Utilities/Doxygen.app/Contents/MacOS DOC "Doxygen documentation generation tool (http://www.doxygen.org)" + VALIDATOR _Doxygen_version_validator ) mark_as_advanced(DOXYGEN_EXECUTABLE) if(DOXYGEN_EXECUTABLE) - execute_process( - COMMAND "${DOXYGEN_EXECUTABLE}" --version - OUTPUT_VARIABLE DOXYGEN_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - RESULT_VARIABLE _Doxygen_version_result - ) + _Doxygen_get_version(DOXYGEN_VERSION _Doxygen_version_result "${DOXYGEN_EXECUTABLE}") + if(_Doxygen_version_result) message(WARNING "Unable to determine doxygen version: ${_Doxygen_version_result}") endif() @@ -642,11 +674,11 @@ endforeach() unset(_comp) # Verify find results -include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) find_package_handle_standard_args( Doxygen REQUIRED_VARS DOXYGEN_EXECUTABLE VERSION_VAR DOXYGEN_VERSION + HANDLE_VERSION_RANGE HANDLE_COMPONENTS ) diff --git a/Modules/FindGDAL.cmake b/Modules/FindGDAL.cmake index 5237e15..e6eac30 100644 --- a/Modules/FindGDAL.cmake +++ b/Modules/FindGDAL.cmake @@ -160,7 +160,7 @@ unset(_gdal_version) unset(_gdal_versions) find_library(GDAL_LIBRARY - NAMES ${_gdal_lib} ${_gdal_libnames} gdal gdal_i gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL + NAMES ${_gdal_lib} ${_gdal_libnames} gdal gdald gdal_i gdal1.5.0 gdal1.4.0 gdal1.3.2 GDAL HINTS ENV GDAL_DIR ENV GDAL_ROOT diff --git a/Modules/FindGLEW.cmake b/Modules/FindGLEW.cmake index b9ebe08..bfde40b 100644 --- a/Modules/FindGLEW.cmake +++ b/Modules/FindGLEW.cmake @@ -63,11 +63,36 @@ This module defines the following variables: #]=======================================================================] include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) find_package(GLEW CONFIG QUIET) if(GLEW_FOUND) find_package_handle_standard_args(GLEW DEFAULT_MSG GLEW_CONFIG) + get_target_property(GLEW_INCLUDE_DIRS GLEW::GLEW INTERFACE_INCLUDE_DIRECTORIES) + set(GLEW_INCLUDE_DIR ${GLEW_INCLUDE_DIRS}) + get_target_property(_GLEW_DEFS GLEW::GLEW INTERFACE_COMPILE_DEFINITIONS) + if("${_GLEW_DEFS}" MATCHES "GLEW_STATIC") + get_target_property(GLEW_LIBRARY_DEBUG GLEW::GLEW IMPORTED_LOCATION_DEBUG) + get_target_property(GLEW_LIBRARY_RELEASE GLEW::GLEW IMPORTED_LOCATION_RELEASE) + else() + get_target_property(GLEW_LIBRARY_DEBUG GLEW::GLEW IMPORTED_IMPLIB_DEBUG) + get_target_property(GLEW_LIBRARY_RELEASE GLEW::GLEW IMPORTED_IMPLIB_RELEASE) + endif() + get_target_property(_GLEW_LINK_INTERFACE GLEW::GLEW IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE) # same for debug and release + list(APPEND GLEW_LIBRARIES ${_GLEW_LINK_INTERFACE}) + list(APPEND GLEW_LIBRARY ${_GLEW_LINK_INTERFACE}) + select_library_configurations(GLEW) + if("${_GLEW_DEFS}" MATCHES "GLEW_STATIC") + set(GLEW_STATIC_LIBRARIES ${GLEW_LIBRARIES}) + else() + set(GLEW_SHARED_LIBRARIES ${GLEW_LIBRARIES}) + endif() + unset(_GLEW_DEFS) + unset(_GLEW_LINK_INTERFACE) + unset(GLEW_LIBRARY) + unset(GLEW_LIBRARY_DEBUG) + unset(GLEW_LIBRARY_RELEASE) return() endif() @@ -171,8 +196,6 @@ find_library(GLEW_STATIC_LIBRARY_DEBUG set(CMAKE_FIND_LIBRARY_SUFFIXES ${__GLEW_CURRENT_FIND_LIBRARY_SUFFIXES}) unset(__GLEW_CURRENT_FIND_LIBRARY_SUFFIXES) -include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) - select_library_configurations(GLEW_SHARED) select_library_configurations(GLEW_STATIC) diff --git a/Modules/FindGLUT.cmake b/Modules/FindGLUT.cmake index 320ddad..e0636b2 100644 --- a/Modules/FindGLUT.cmake +++ b/Modules/FindGLUT.cmake @@ -67,83 +67,39 @@ The following variables may also be provided, for backwards compatibility: include(${CMAKE_CURRENT_LIST_DIR}/SelectLibraryConfigurations.cmake) include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -function(_add_glut_target_simple) - if(TARGET GLUT::GLUT) - return() - endif() - add_library(GLUT::GLUT INTERFACE IMPORTED) - if(GLUT_INCLUDE_DIRS) - target_include_directories(GLUT::GLUT SYSTEM - INTERFACE "${GLUT_INCLUDE_DIRS}") - endif() - if(GLUT_LIBRARIES) - target_link_libraries(GLUT::GLUT INTERFACE ${GLUT_LIBRARIES}) - endif() - if(GLUT_LIBRARY_DIRS) - target_link_directories(GLUT::GLUT INTERFACE ${GLUT_LIBRARY_DIRS}) - endif() - if(GLUT_LDFLAGS) - target_link_options(GLUT::GLUT INTERFACE ${GLUT_LDFLAGS}) - endif() - if(GLUT_CFLAGS) - separate_arguments(GLUT_CFLAGS_SPLIT UNIX_COMMAND "${GLUT_CFLAGS}") - target_compile_options(GLUT::GLUT INTERFACE ${GLUT_CFLAGS_SPLIT}) - endif() - - set_property(TARGET GLUT::GLUT APPEND PROPERTY - IMPORTED_LOCATION "${GLUT_glut_LIBRARY}") -endfunction() - find_package(PkgConfig QUIET) -if(PKG_CONFIG_FOUND) - # Tell pkg-config not to strip any -I flags to make sure GLUT_INCLUDE_DIRS - # will be defined. - if(DEFINED ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS}) - set(_pkgconfig_allow_system_cflags_old "$ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS}") - else() - unset(_pkgconfig_allow_system_cflags_old) - endif() - set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} 1) - pkg_check_modules(GLUT QUIET glut) - if(DEFINED _pkgconfig_allow_system_cflags_old) - set(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS} "${_pkgconfig_allow_system_cflags_old}") - unset(_pkgconfig_allow_system_cflags_old) - else() - unset(ENV{PKG_CONFIG_ALLOW_SYSTEM_CFLAGS}) - endif() - if(NOT GLUT_FOUND) - pkg_check_modules(GLUT QUIET freeglut) - endif() - if(GLUT_FOUND) - # GLUT_INCLUDE_DIRS is now the official result variable, but - # older versions of CMake only provided GLUT_INCLUDE_DIR. - set(GLUT_INCLUDE_DIR "${GLUT_INCLUDE_DIRS}") - _add_glut_target_simple() - FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLUT REQUIRED_VARS GLUT_FOUND) - return() - endif() +pkg_check_modules(PC_GLUT QUIET glut) +if(NOT PC_GLUT_FOUND) + pkg_check_modules(PC_GLUT QUIET freeglut) endif() if(WIN32) find_path( GLUT_INCLUDE_DIR NAMES GL/glut.h - PATHS ${GLUT_ROOT_PATH}/include ) + PATHS ${GLUT_ROOT_PATH}/include + HINTS ${PC_GLUT_INCLUDE_DIRS}) mark_as_advanced(GLUT_INCLUDE_DIR) find_library( GLUT_glut_LIBRARY_RELEASE NAMES freeglut glut glut32 PATHS ${OPENGL_LIBRARY_DIR} ${GLUT_ROOT_PATH}/Release + HINTS + ${PC_GLUT_LIBRARY_DIRS} ) +# N.B. As the pkg-config cannot distinguish between release and debug libraries, +# assume that their hint was the both Debug and Release library. find_library( GLUT_glut_LIBRARY_DEBUG NAMES freeglutd PATHS ${OPENGL_LIBRARY_DIR} ${GLUT_ROOT_PATH}/Debug + HINTS + ${PC_GLUT_LIBRARY_DIRS} ) mark_as_advanced(GLUT_glut_LIBRARY_RELEASE GLUT_glut_LIBRARY_DEBUG) select_library_configurations(GLUT_glut) elseif(APPLE) - find_path(GLUT_INCLUDE_DIR glut.h ${OPENGL_LIBRARY_DIR}) + find_path(GLUT_INCLUDE_DIR glut.h PATHS ${OPENGL_LIBRARY_DIR} HINTS ${PC_GLUT_INCLUDE_DIRS}) mark_as_advanced(GLUT_INCLUDE_DIR) - find_library(GLUT_glut_LIBRARY GLUT DOC "GLUT library for OSX") + find_library(GLUT_glut_LIBRARY GLUT HINTS ${PC_GLUT_LIBRARY_DIRS} DOC "GLUT library for OSX") find_library(GLUT_cocoa_LIBRARY Cocoa DOC "Cocoa framework for OSX") mark_as_advanced(GLUT_glut_LIBRARY GLUT_cocoa_LIBRARY) @@ -192,18 +148,24 @@ else() endif () find_path( GLUT_INCLUDE_DIR GL/glut.h + PATHS /usr/include/GL /usr/openwin/share/include /usr/openwin/include /opt/graphics/OpenGL/include /opt/graphics/OpenGL/contrib/libglut ${_GLUT_INC_DIR} + HINTS + ${PC_GLUT_INCLUDE_DIRS} ) mark_as_advanced(GLUT_INCLUDE_DIR) find_library( GLUT_glut_LIBRARY glut + PATHS /usr/openwin/lib ${_GLUT_glut_LIB_DIR} + HINTS + ${PC_GLUT_LIBRARY_DIRS} ) mark_as_advanced(GLUT_glut_LIBRARY) diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake index 00bfc29..4634876 100644 --- a/Modules/FindGTK2.cmake +++ b/Modules/FindGTK2.cmake @@ -313,6 +313,7 @@ function(_GTK2_FIND_INCLUDE_DIR _var _hdr) /usr/openwin/lib /sw/lib /opt/local/lib + /opt/homebrew/lib /usr/pkg/lib /usr/pkg/include/glib $ENV{GTKMM_BASEPATH}/include diff --git a/Modules/FindHDF5.cmake b/Modules/FindHDF5.cmake index 40ed9a9..d662a7d 100644 --- a/Modules/FindHDF5.cmake +++ b/Modules/FindHDF5.cmake @@ -238,7 +238,7 @@ function(_HDF5_test_regular_compiler_C success version is_parallel) " fid = H5Fcreate(\"foo.h5\",H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);\n" " return 0;\n" "}") - try_compile(${success} ${scratch_directory} ${test_file} + try_compile(${success} SOURCES ${test_file} COPY_FILE ${scratch_directory}/compiler_has_h5_c ) endif() @@ -286,7 +286,7 @@ function(_HDF5_test_regular_compiler_CXX success version is_parallel) " H5File file(\"foo.h5\", H5F_ACC_TRUNC);\n" " return 0;\n" "}") - try_compile(${success} ${scratch_directory} ${test_file} + try_compile(${success} SOURCES ${test_file} COPY_FILE ${scratch_directory}/compiler_has_h5_cxx ) endif() @@ -323,7 +323,7 @@ function(_HDF5_test_regular_compiler_Fortran success is_parallel) " call h5open_f(error)\n" " call h5close_f(error)\n" "end\n") - try_compile(${success} ${scratch_directory} ${test_file}) + try_compile(${success} SOURCES ${test_file}) if(${success}) execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -showconfig OUTPUT_VARIABLE config_output diff --git a/Modules/FindICU.cmake b/Modules/FindICU.cmake index 91dcba5..b4f4d71 100644 --- a/Modules/FindICU.cmake +++ b/Modules/FindICU.cmake @@ -254,13 +254,6 @@ function(_ICU_FIND) set("${component_found}" ON) set("${component_found_compat}" ON) list(APPEND ICU_LIBRARY "${${component_cache}}") - endif() - mark_as_advanced("${component_found}") - mark_as_advanced("${component_found_compat}") - set("${component_cache}" "${${component_cache}}" PARENT_SCOPE) - set("${component_found}" "${${component_found}}" PARENT_SCOPE) - set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE) - if(component_found OR component_found_compat) if (ICU_FIND_REQUIRED_${component}) list(APPEND ICU_LIBS_FOUND "${component} (required): ${${component_cache}}") else() @@ -274,6 +267,11 @@ function(_ICU_FIND) list(APPEND ICU_LIBS_NOTFOUND "${component} (optional)") endif() endif() + mark_as_advanced("${component_found}") + mark_as_advanced("${component_found_compat}") + set("${component_cache}" "${${component_cache}}" PARENT_SCOPE) + set("${component_found}" "${${component_found}}" PARENT_SCOPE) + set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE) endforeach() set(_ICU_REQUIRED_LIBS_FOUND "${ICU_REQUIRED_LIBS_FOUND}" PARENT_SCOPE) set(ICU_LIBRARY "${ICU_LIBRARY}" PARENT_SCOPE) diff --git a/Modules/FindLAPACK.cmake b/Modules/FindLAPACK.cmake index b08b359..4151116 100644 --- a/Modules/FindLAPACK.cmake +++ b/Modules/FindLAPACK.cmake @@ -35,6 +35,13 @@ The following variables may be set to influence this module's behavior: if set ``pkg-config`` will be used to search for a LAPACK library first and if one is found that is preferred +``BLA_PKGCONFIG_LAPACK`` + .. versionadded:: 3.25 + + If set, the ``pkg-config`` method will look for this module name instead of + just ``lapack``. + + ``BLA_SIZEOF_INTEGER`` .. versionadded:: 3.22 @@ -278,8 +285,11 @@ endif() # Search with pkg-config if specified if(BLA_PREFER_PKGCONFIG) + if(NOT BLA_PKGCONFIG_LAPACK) + set(BLA_PKGCONFIG_LAPACK "lapack") + endif() find_package(PkgConfig QUIET) - pkg_check_modules(PKGC_LAPACK QUIET lapack) + pkg_check_modules(PKGC_LAPACK QUIET ${BLA_PKGCONFIG_LAPACK}) if(PKGC_LAPACK_FOUND) set(LAPACK_FOUND TRUE) set(LAPACK_LIBRARIES "${PKGC_LAPACK_LINK_LIBRARIES}") diff --git a/Modules/FindLibArchive.cmake b/Modules/FindLibArchive.cmake index 08078a2..9d3ac13 100644 --- a/Modules/FindLibArchive.cmake +++ b/Modules/FindLibArchive.cmake @@ -26,6 +26,9 @@ The module defines the following ``IMPORTED`` targets: .. versionadded:: 3.6 Support for new libarchive 3.2 version string format. +.. versionadded:: 3.17 + Provides an imported target. + #]=======================================================================] find_path(LibArchive_INCLUDE_DIR diff --git a/Modules/FindMFC.cmake b/Modules/FindMFC.cmake index b8ca71b..2d5de89 100644 --- a/Modules/FindMFC.cmake +++ b/Modules/FindMFC.cmake @@ -29,23 +29,19 @@ endif() if(MFC_ATTEMPT_TRY_COMPILE) if(NOT DEFINED MFC_HAVE_MFC) set(CHECK_INCLUDE_FILE_VAR "afxwin.h") - configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx) + file(READ ${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in _CIF_SOURCE_CONTENT) + string(CONFIGURE "${_CIF_SOURCE_CONTENT}" _CIF_SOURCE_CONTENT) message(CHECK_START "Looking for MFC") # Try both shared and static as the root project may have set the /MT flag try_compile(MFC_HAVE_MFC - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx + SOURCE_FROM_VAR CheckIncludeFile.cxx _CIF_SOURCE_CONTENT CMAKE_FLAGS -DCMAKE_MFC_FLAG:STRING=2 -DCOMPILE_DEFINITIONS:STRING=-D_AFXDLL OUTPUT_VARIABLE OUTPUT) if(NOT MFC_HAVE_MFC) - configure_file(${CMAKE_ROOT}/Modules/CheckIncludeFile.cxx.in - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx) try_compile(MFC_HAVE_MFC - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckIncludeFile.cxx + SOURCE_FROM_VAR CheckIncludeFile.cxx _CIF_SOURCE_CONTENT CMAKE_FLAGS -DCMAKE_MFC_FLAG:STRING=1 OUTPUT_VARIABLE OUTPUT) diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake index bca0c10..e15be91 100644 --- a/Modules/FindMPI.cmake +++ b/Modules/FindMPI.cmake @@ -391,11 +391,11 @@ function (_MPI_check_compiler LANG QUERY_FLAG OUTPUT_VARIABLE RESULT_VARIABLE) # library that has invalid or missing version information there would be warning # messages emitted by ld.so in the compiler output. In either case, we'll treat # the output as invalid. - if("${WRAPPER_OUTPUT}" MATCHES "undefined reference|unrecognized|need to set|no version information available|command not found") + if(WRAPPER_OUTPUT MATCHES "undefined reference|unrecognized|need to set|no version information available|command not found") set(WRAPPER_RETURN 255) endif() # Ensure that no error output might be passed upwards. - if(NOT WRAPPER_RETURN EQUAL 0) + if(NOT WRAPPER_RETURN EQUAL "0") unset(WRAPPER_OUTPUT) else() # Strip leading whitespace @@ -441,13 +441,13 @@ function (_MPI_interrogate_compiler LANG) if(MSVC) get_filename_component(_MPI_UNDERLAYING_COMPILER "${_MPI_UNDERLAYING_COMPILER}" NAME) endif() - if("${LANG}" STREQUAL "C") + if(LANG STREQUAL "C") _MPI_env_set_ifnot(I_MPI_CC _MPI_UNDERLAYING_COMPILER) _MPI_env_set_ifnot(MPICH_CC _MPI_UNDERLAYING_COMPILER) - elseif("${LANG}" STREQUAL "CXX") + elseif(LANG STREQUAL "CXX") _MPI_env_set_ifnot(I_MPI_CXX _MPI_UNDERLAYING_COMPILER) _MPI_env_set_ifnot(MPICH_CXX _MPI_UNDERLAYING_COMPILER) - elseif("${LANG}" STREQUAL "Fortran") + elseif(LANG STREQUAL "Fortran") _MPI_env_set_ifnot(I_MPI_FC _MPI_UNDERLAYING_COMPILER) _MPI_env_set_ifnot(MPICH_FC _MPI_UNDERLAYING_COMPILER) _MPI_env_set_ifnot(I_MPI_F77 _MPI_UNDERLAYING_COMPILER) @@ -470,10 +470,10 @@ function (_MPI_interrogate_compiler LANG) # or a newer version of LAM/MPI, and implies that -showme:link will also work. # Open MPI also supports -show, but separates linker and compiler information _MPI_check_compiler(${LANG} "-showme:compile" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) - if (MPI_COMPILER_RETURN EQUAL 0) + if (MPI_COMPILER_RETURN EQUAL "0") _MPI_check_compiler(${LANG} "-showme:link" MPI_LINK_CMDLINE MPI_COMPILER_RETURN) - if (NOT MPI_COMPILER_RETURN EQUAL 0) + if (NOT MPI_COMPILER_RETURN EQUAL "0") unset(MPI_COMPILE_CMDLINE) endif() endif() @@ -482,13 +482,13 @@ function (_MPI_interrogate_compiler LANG) # For modern versions, both do the same as -show. However, for old versions, they do differ # when called for mpicxx and mpif90 and it's necessary to use them over -show in order to find the # removed MPI C++ bindings. - if (NOT MPI_COMPILER_RETURN EQUAL 0) + if (NOT MPI_COMPILER_RETURN EQUAL "0") _MPI_check_compiler(${LANG} "-compile-info" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) - if (MPI_COMPILER_RETURN EQUAL 0) + if (MPI_COMPILER_RETURN EQUAL "0") _MPI_check_compiler(${LANG} "-link-info" MPI_LINK_CMDLINE MPI_COMPILER_RETURN) - if (NOT MPI_COMPILER_RETURN EQUAL 0) + if (NOT MPI_COMPILER_RETURN EQUAL "0") unset(MPI_COMPILE_CMDLINE) endif() endif() @@ -496,18 +496,18 @@ function (_MPI_interrogate_compiler LANG) # Cray compiler wrappers come usually without a separate mpicc/c++/ftn, but offer # --cray-print-opts=... - if (NOT MPI_COMPILER_RETURN EQUAL 0) + if (NOT MPI_COMPILER_RETURN EQUAL "0") _MPI_check_compiler(${LANG} "--cray-print-opts=cflags" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) - if (MPI_COMPILER_RETURN EQUAL 0) + if (MPI_COMPILER_RETURN EQUAL "0") # Pass --no-as-needed so the mpi library is always linked. Otherwise, the # Cray compiler wrapper puts an --as-needed flag around the mpi library, # and it is not linked unless code directly refers to it. _MPI_check_compiler(${LANG} "--no-as-needed;--cray-print-opts=libs" MPI_LINK_CMDLINE MPI_COMPILER_RETURN) - if (NOT MPI_COMPILER_RETURN EQUAL 0) + if (NOT MPI_COMPILER_RETURN EQUAL "0") unset(MPI_COMPILE_CMDLINE) unset(MPI_LINK_CMDLINE) endif() @@ -516,24 +516,24 @@ function (_MPI_interrogate_compiler LANG) # MPICH, MVAPICH2 and Intel MPI just use "-show". Open MPI also offers this, but the # -showme commands are more specialized. - if (NOT MPI_COMPILER_RETURN EQUAL 0) + if (NOT MPI_COMPILER_RETURN EQUAL "0") _MPI_check_compiler(${LANG} "-show" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) endif() # Older versions of LAM/MPI have "-showme". Open MPI also supports this. # Unknown to MPICH, MVAPICH and Intel MPI. - if (NOT MPI_COMPILER_RETURN EQUAL 0) + if (NOT MPI_COMPILER_RETURN EQUAL "0") _MPI_check_compiler(${LANG} "-showme" MPI_COMPILE_CMDLINE MPI_COMPILER_RETURN) endif() - if (MPI_COMPILER_RETURN EQUAL 0 AND DEFINED MPI_COMPILE_CMDLINE) + if (MPI_COMPILER_RETURN EQUAL "0" AND DEFINED MPI_COMPILE_CMDLINE) # Intel MPI can be run with -compchk or I_MPI_CHECK_COMPILER set to 1. # In this case, -show will be prepended with a line to the compiler checker. This is a script that performs # compatibility checks and returns a non-zero exit code together with an error if something fails. # It has to be called as "compchk.sh <arch> <compiler>". Here, <arch> is one out of 32 (i686), 64 (ia64) or 32e (x86_64). # The compiler is identified by filename, and can be either the MPI compiler or the underlying compiler. # NOTE: It is vital to run this script while the environment variables are set up, otherwise it can check the wrong compiler. - if("${MPI_COMPILE_CMDLINE}" MATCHES "^([^\" ]+/compchk.sh|\"[^\"]+/compchk.sh\") +([^ ]+)") + if(MPI_COMPILE_CMDLINE MATCHES "^([^\" ]+/compchk.sh|\"[^\"]+/compchk.sh\") +([^ ]+)") # Now CMAKE_MATCH_1 contains the path to the compchk.sh file and CMAKE_MATCH_2 the architecture flag. unset(COMPILER_CHECKER_OUTPUT) execute_process( @@ -542,7 +542,7 @@ function (_MPI_interrogate_compiler LANG) ERROR_VARIABLE COMPILER_CHECKER_OUTPUT ERROR_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE MPI_COMPILER_RETURN) # If it returned a non-zero value, the check below will fail and cause the interrogation to be aborted. - if(NOT MPI_COMPILER_RETURN EQUAL 0) + if(NOT MPI_COMPILER_RETURN EQUAL "0") if(NOT MPI_FIND_QUIETLY) message(STATUS "Intel MPI compiler check failed: ${COMPILER_CHECKER_OUTPUT}") endif() @@ -554,13 +554,13 @@ function (_MPI_interrogate_compiler LANG) endif() # Revert changes to the environment made previously - if("${LANG}" STREQUAL "C") + if(LANG STREQUAL "C") _MPI_env_unset_ifnot(I_MPI_CC) _MPI_env_unset_ifnot(MPICH_CC) - elseif("${LANG}" STREQUAL "CXX") + elseif(LANG STREQUAL "CXX") _MPI_env_unset_ifnot(I_MPI_CXX) _MPI_env_unset_ifnot(MPICH_CXX) - elseif("${LANG}" STREQUAL "Fortran") + elseif(LANG STREQUAL "Fortran") _MPI_env_unset_ifnot(I_MPI_FC) _MPI_env_unset_ifnot(MPICH_FC) _MPI_env_unset_ifnot(I_MPI_F77) @@ -572,7 +572,7 @@ function (_MPI_interrogate_compiler LANG) _MPI_env_unset_ifnot(I_MPI_DEBUG_INFO_STRIP) _MPI_env_unset_ifnot(I_MPI_FORT_BIND) - if (NOT (MPI_COMPILER_RETURN EQUAL 0) OR NOT (DEFINED MPI_COMPILE_CMDLINE)) + if (NOT (MPI_COMPILER_RETURN EQUAL "0") OR NOT (DEFINED MPI_COMPILE_CMDLINE)) # Cannot interrogate this compiler, so exit. set(MPI_${LANG}_WRAPPER_FOUND FALSE PARENT_SCOPE) return() @@ -613,13 +613,13 @@ function (_MPI_interrogate_compiler LANG) if(UNIX) # At this point, we obtained some output from a compiler wrapper that works. # We'll now try to parse it into variables with meaning to us. - if("${LANG}" STREQUAL "Fortran") + if(LANG STREQUAL "Fortran") # If MPICH (and derivates) didn't recognize the Fortran compiler include flag during configuration, # they'll return a set of three commands, consisting out of a symlink command for mpif.h, # the actual compiler command and deletion of the created symlink. # Especially with M(VA)PICH-1, this appears to happen erroneously, and therefore we should translate # this output into an additional include directory and then drop it from the output. - if("${MPI_COMPILE_CMDLINE}" MATCHES "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h") + if(MPI_COMPILE_CMDLINE MATCHES "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h") get_filename_component(MPI_INCLUDE_DIRS_WORK "${CMAKE_MATCH_1}" DIRECTORY) string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_COMPILE_CMDLINE "${MPI_COMPILE_CMDLINE}") string(REGEX REPLACE "^ln -s ([^\" ]+|\"[^\"]+\") mpif.h\n" "" MPI_LINK_CMDLINE "${MPI_LINK_CMDLINE}") @@ -651,7 +651,7 @@ function (_MPI_interrogate_compiler LANG) # produce inconsistent results with the regularly flags. # Similarly, aliasing flags do not belong into our flag array. # Also strip out `-framework` flags. - if(NOT "${_MPI_COMPILE_OPTION}" MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce]|ramework)") + if(NOT _MPI_COMPILE_OPTION MATCHES "^-f((no-|)(stack-protector|strict-aliasing)|PI[CE]|pi[ce]|ramework)") list(APPEND MPI_COMPILE_OPTIONS_WORK "${_MPI_COMPILE_OPTION}") endif() endforeach() @@ -673,7 +673,7 @@ function (_MPI_interrogate_compiler LANG) foreach(_MPI_COMPILE_DEFINITION IN LISTS MPI_ALL_COMPILE_DEFINITIONS) string(REGEX REPLACE "^ ?${_MPI_PREPROCESSOR_FLAG_REGEX}-D *" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}") string(REPLACE "\"" "" _MPI_COMPILE_DEFINITION "${_MPI_COMPILE_DEFINITION}") - if(NOT "${_MPI_COMPILE_DEFINITION}" MATCHES "^_FORTIFY_SOURCE.*") + if(NOT _MPI_COMPILE_DEFINITION MATCHES "^_FORTIFY_SOURCE.*") list(APPEND MPI_COMPILE_DEFINITIONS_WORK "${_MPI_COMPILE_DEFINITION}") endif() endforeach() @@ -788,7 +788,7 @@ function (_MPI_interrogate_compiler LANG) # decide how to link it based on file type, not based on a prefix like 'lib'. set(_MPI_LIB_SUFFIX_REGEX "${CMAKE_STATIC_LIBRARY_SUFFIX}") if(DEFINED CMAKE_IMPORT_LIBRARY_SUFFIX) - if(NOT ("${CMAKE_IMPORT_LIBRARY_SUFFIX}" STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}")) + if(NOT (CMAKE_IMPORT_LIBRARY_SUFFIX STREQUAL CMAKE_STATIC_LIBRARY_SUFFIX)) string(APPEND _MPI_LIB_SUFFIX_REGEX "|${CMAKE_IMPORT_LIBRARY_SUFFIX}") endif() else() @@ -804,7 +804,7 @@ function (_MPI_interrogate_compiler LANG) if(_MPI_LIB_NAME_TEST STREQUAL "") string(REGEX REPLACE "^ +\"?|\"? +$" "" _MPI_LIB_NAME "${_MPI_LIB_NAME}") get_filename_component(_MPI_LIB_PATH "${_MPI_LIB_NAME}" DIRECTORY) - if(NOT "${_MPI_LIB_PATH}" STREQUAL "") + if(NOT _MPI_LIB_PATH STREQUAL "") list(APPEND MPI_LIB_FULLPATHS_WORK "${_MPI_LIB_NAME}") else() list(APPEND MPI_LIB_NAMES_WORK "${_MPI_LIB_NAME}") @@ -845,7 +845,7 @@ function (_MPI_interrogate_compiler LANG) foreach(_MPI_LINK_DIRECTORY IN LISTS MPI_LINK_DIRECTORIES_LEFTOVER) file(TO_NATIVE_PATH "${_MPI_LINK_DIRECTORY}" _MPI_LINK_DIRECTORY_ACTUAL) string(FIND "${_MPI_LINK_DIRECTORY_ACTUAL}" " " _MPI_LINK_DIRECTORY_CONTAINS_SPACE) - if(NOT _MPI_LINK_DIRECTORY_CONTAINS_SPACE EQUAL -1) + if(NOT _MPI_LINK_DIRECTORY_CONTAINS_SPACE EQUAL "-1") set(_MPI_LINK_DIRECTORY_ACTUAL "\"${_MPI_LINK_DIRECTORY_ACTUAL}\"") endif() if(MPI_LINK_FLAGS_WORK) @@ -871,7 +871,7 @@ function (_MPI_interrogate_compiler LANG) # MPI might require pthread to work. The above mechanism wouldn't detect it, but we need to # link it in that case. -lpthread is covered by the normal library treatment on the other hand. - if("${MPI_COMPILE_CMDLINE}" MATCHES "-pthread") + if(MPI_COMPILE_CMDLINE MATCHES "-pthread") list(APPEND MPI_COMPILE_OPTIONS_WORK "-pthread") if(MPI_LINK_FLAGS_WORK) string(APPEND MPI_LINK_FLAGS_WORK " -pthread") @@ -918,10 +918,10 @@ function(_MPI_guess_settings LANG) # The environment variables MSMPI_INC and MSMPILIB32/64 are the only ways of locating the MSMPI_SDK, # which is installed separately from the runtime. Thus it's possible to have mpiexec but not MPI headers # or import libraries and vice versa. - if(NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MSMPI") + if(NOT MPI_GUESS_LIBRARY_NAME OR MPI_GUESS_LIBRARY_NAME STREQUAL "MSMPI") # We first attempt to locate the msmpi.lib. Should be find it, we'll assume that the MPI present is indeed # Microsoft MPI. - if("${CMAKE_SIZEOF_VOID_P}" EQUAL 8) + if(CMAKE_SIZEOF_VOID_P EQUAL "8") file(TO_CMAKE_PATH "$ENV{MSMPI_LIB64}" MPI_MSMPI_LIB_PATH) file(TO_CMAKE_PATH "$ENV{MSMPI_INC}/x64" MPI_MSMPI_INC_PATH_EXTRA) else() @@ -975,9 +975,9 @@ function(_MPI_guess_settings LANG) # Our strategy is now to locate all libraries, but enter msmpifec into the LIB_NAMES array. # Should this not be adequate it's a straightforward way for a user to change the LIB_NAMES array and # have his library found. Still, this should not be necessary outside of exceptional cases, as reasoned. - if ("${LANG}" STREQUAL "Fortran") + if (LANG STREQUAL "Fortran") set(MPI_MSMPI_CALLINGCONVS c) - if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4) + if(CMAKE_SIZEOF_VOID_P EQUAL "4") list(APPEND MPI_MSMPI_CALLINGCONVS s) endif() foreach(mpistrlenpos IN ITEMS e m) @@ -1025,7 +1025,7 @@ function(_MPI_guess_settings LANG) # At this point there's not many MPIs that we could still consider. # OpenMPI 1.6.x and below supported Windows, but these ship compiler wrappers that still work. # The only other relevant MPI implementation without a wrapper is MPICH2, which had Windows support in 1.4.1p1 and older. - if(NOT MPI_GUESS_FOUND AND (NOT MPI_GUESS_LIBRARY_NAME OR "${MPI_GUESS_LIBRARY_NAME}" STREQUAL "MPICH2")) + if(NOT MPI_GUESS_FOUND AND (NOT MPI_GUESS_LIBRARY_NAME OR MPI_GUESS_LIBRARY_NAME STREQUAL "MPICH2")) set(MPI_MPICH_PREFIX_PATHS "$ENV{ProgramW6432}/MPICH2/lib" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MPICH\\SMPD;binary]/../lib" @@ -1042,7 +1042,7 @@ function(_MPI_guess_settings LANG) set(MPI_MPICH_LIB_NAMES "mpi") # If MPI-2 C++ bindings are requested, we need to locate cxx.lib as well. # Otherwise, MPICH_SKIP_MPICXX will be defined and these bindings aren't needed. - if("${LANG}" STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX) + if(LANG STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX) find_library(MPI_cxx_LIBRARY NAMES cxx HINTS ${MPI_MPICH_PREFIX_PATHS}) @@ -1055,7 +1055,7 @@ function(_MPI_guess_settings LANG) # fmpich2s.lib would be useful for Compaq Visual Fortran, fmpich2g.lib has to be used with GNU g77 and is also # provided in the form of an .a archive for MinGW and Cygwin. From our perspective, fmpich2.lib is the only one # we need to try, and if it doesn't work with the given Fortran compiler we'd find out later on during validation - elseif("${LANG}" STREQUAL "Fortran") + elseif(LANG STREQUAL "Fortran") find_library(MPI_fmpich2_LIBRARY NAMES fmpich2 HINTS ${MPI_MPICH_PREFIX_PATHS}) @@ -1103,7 +1103,7 @@ function(_MPI_guess_settings LANG) endfunction() function(_MPI_adjust_compile_definitions LANG) - if("${LANG}" STREQUAL "CXX") + if(LANG STREQUAL "CXX") # To disable the C++ bindings, we need to pass some definitions since the mpi.h header has to deal with both C and C++ # bindings in MPI-2. if(MPI_CXX_SKIP_MPICXX AND NOT MPI_${LANG}_COMPILE_DEFINITIONS MATCHES "SKIP_MPICXX") @@ -1119,7 +1119,7 @@ endfunction() macro(_MPI_assemble_libraries LANG) set(MPI_${LANG}_LIBRARIES "") # Only for libraries do we need to check whether the compiler's linking stage is separate. - if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_${LANG}_WORKS_IMPLICIT) + if(NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER OR NOT MPI_${LANG}_WORKS_IMPLICIT) foreach(mpilib IN LISTS MPI_${LANG}_LIB_NAMES) list(APPEND MPI_${LANG}_LIBRARIES ${MPI_${mpilib}_LIBRARY}) endforeach() @@ -1131,7 +1131,7 @@ macro(_MPI_assemble_include_dirs LANG) ${MPI_${LANG}_COMPILER_INCLUDE_DIRS} ${MPI_${LANG}_ADDITIONAL_INCLUDE_DIRS} ) - if("${LANG}" MATCHES "(C|CXX)") + if(LANG MATCHES "^(C|CXX)$") if(MPI_${LANG}_HEADER_DIR) list(APPEND MPI_${LANG}_INCLUDE_DIRS "${MPI_${LANG}_HEADER_DIR}") endif() @@ -1156,7 +1156,7 @@ macro(_MPI_split_include_dirs LANG) # We try to find the headers/modules among those paths (and system paths) # For C/C++, we just need to have a look for mpi.h. - if("${LANG}" MATCHES "(C|CXX)") + if(LANG MATCHES "^(C|CXX)$") find_path(MPI_${LANG}_HEADER_DIR "mpi.h" HINTS ${MPI_${LANG}_COMPILER_INCLUDE_DIRS} @@ -1171,7 +1171,7 @@ macro(_MPI_split_include_dirs LANG) # any of the Fortran 77/90/2008 APIs for MPI. For example, MSMPI # only provides Fortran 77 and - if mpi.f90 is built - potentially # a Fortran 90 module. - elseif("${LANG}" STREQUAL "Fortran") + elseif(LANG STREQUAL "Fortran") find_path(MPI_${LANG}_F77_HEADER_DIR "mpif.h" HINTS ${MPI_${LANG}_COMPILER_INCLUDE_DIRS} @@ -1238,28 +1238,30 @@ function(_MPI_try_staged_settings LANG MPI_TEST_FILE_NAME MODE RUN_BINARY SUPPRE set(SRC_DIR "${CMAKE_ROOT}/Modules/FindMPI") set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindMPI/${MPI_TEST_FILE_NAME}_${LANG}.bin") unset(MPI_TEST_COMPILE_DEFINITIONS) - if("${LANG}" STREQUAL "Fortran") - if("${MODE}" STREQUAL "F90_MODULE") + if(LANG STREQUAL "Fortran") + if(MODE STREQUAL "F90_MODULE") set(MPI_Fortran_INCLUDE_LINE "use mpi\n implicit none") - elseif("${MODE}" STREQUAL "F08_MODULE") + elseif(MODE STREQUAL "F08_MODULE") set(MPI_Fortran_INCLUDE_LINE "use mpi_f08\n implicit none") else() # F77 header set(MPI_Fortran_INCLUDE_LINE "implicit none\n include 'mpif.h'") endif() - configure_file("${SRC_DIR}/${MPI_TEST_FILE_NAME}.f90.in" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90" @ONLY) - set(MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.f90") - elseif("${LANG}" STREQUAL "CXX") - configure_file("${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp" COPYONLY) - set(MPI_TEST_SOURCE_FILE "${WORK_DIR}/${MPI_TEST_FILE_NAME}.cpp") - if("${MODE}" STREQUAL "TEST_MPICXX") + file(READ "${SRC_DIR}/${MPI_TEST_FILE_NAME}.f90.in" MPI_TEST_SOURCE_CONTENT) + string(CONFIGURE "${MPI_TEST_SOURCE_CONTENT}" MPI_TEST_SOURCE_CONTENT) + set(MPI_TEST_SOURCE_FILE "${MPI_TEST_FILE_NAME}.f90") + elseif(LANG STREQUAL "CXX") + file(READ "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" MPI_TEST_SOURCE_CONTENT) + set(MPI_TEST_SOURCE_FILE "${MPI_TEST_FILE_NAME}.cpp") + if(MODE STREQUAL "TEST_MPICXX") set(MPI_TEST_COMPILE_DEFINITIONS TEST_MPI_MPICXX) endif() else() # C - set(MPI_TEST_SOURCE_FILE "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c") + file(READ "${SRC_DIR}/${MPI_TEST_FILE_NAME}.c" MPI_TEST_SOURCE_CONTENT) + set(MPI_TEST_SOURCE_FILE "${MPI_TEST_FILE_NAME}.c") endif() if(RUN_BINARY) try_run(MPI_RUN_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} MPI_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} - "${CMAKE_BINARY_DIR}" SOURCES "${MPI_TEST_SOURCE_FILE}" + SOURCE_FROM_VAR "${MPI_TEST_SOURCE_FILE}" MPI_TEST_SOURCE_CONTENT COMPILE_DEFINITIONS ${MPI_TEST_COMPILE_DEFINITIONS} LINK_LIBRARIES MPI::MPI_${LANG} RUN_OUTPUT_VARIABLE MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} @@ -1267,7 +1269,7 @@ function(_MPI_try_staged_settings LANG MPI_TEST_FILE_NAME MODE RUN_BINARY SUPPRE set(MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} "${MPI_RUN_OUTPUT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE}}" PARENT_SCOPE) else() try_compile(MPI_RESULT_${LANG}_${MPI_TEST_FILE_NAME}_${MODE} - "${CMAKE_BINARY_DIR}" SOURCES "${MPI_TEST_SOURCE_FILE}" + SOURCE_FROM_VAR "${MPI_TEST_SOURCE_FILE}" MPI_TEST_SOURCE_CONTENT COMPILE_DEFINITIONS ${MPI_TEST_COMPILE_DEFINITIONS} LINK_LIBRARIES MPI::MPI_${LANG} COPY_FILE "${BIN_FILE}" @@ -1290,7 +1292,7 @@ macro(_MPI_check_lang_works LANG SUPPRESS_ERRORS) # - *both*, the mpi module and 'mpif.h' # Since older MPI standards (MPI-1) did not define anything but 'mpif.h', we need to check all three individually. if( NOT MPI_${LANG}_WORKS ) - if("${LANG}" STREQUAL "Fortran") + if(LANG STREQUAL "Fortran") set(MPI_Fortran_INTEGER_LINE "(kind=MPI_INTEGER_KIND)") _MPI_try_staged_settings(${LANG} test_mpi F77_HEADER FALSE ${SUPPRESS_ERRORS}) _MPI_try_staged_settings(${LANG} test_mpi F90_MODULE FALSE ${SUPPRESS_ERRORS}) @@ -1339,11 +1341,11 @@ macro(MPI_search_mpi_prefix_folder PREFIX_FOLDER) endmacro() set(MPI_HINT_DIRS ${MPI_HOME} $ENV{MPI_HOME} $ENV{I_MPI_ROOT}) -if("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Linux") +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") # SUSE Linux Enterprise Server stores its MPI implementations under /usr/lib64/mpi/gcc/<name> # We enumerate the subfolders and append each as a prefix MPI_search_mpi_prefix_folder("/usr/lib64/mpi/gcc") -elseif("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "FreeBSD") +elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "FreeBSD") # FreeBSD ships mpich under the normal system paths - but available openmpi implementations # will be found in /usr/local/mpi/<name> MPI_search_mpi_prefix_folder("/usr/local/mpi") @@ -1410,7 +1412,7 @@ if(NOT MPI_IGNORE_LEGACY_VARIABLES) if(MPI_${LANG}_COMPILE_FLAGS) separate_arguments(MPI_SEPARATE_FLAGS NATIVE_COMMAND "${MPI_${LANG}_COMPILE_FLAGS}") foreach(_MPI_FLAG IN LISTS MPI_SEPARATE_FLAGS) - if("${_MPI_FLAG}" MATCHES "^ *-D([^ ]+)") + if(_MPI_FLAG MATCHES "^ *-D([^ ]+)") list(APPEND MPI_${LANG}_EXTRA_COMPILE_DEFINITIONS "${CMAKE_MATCH_1}") else() list(APPEND MPI_${LANG}_EXTRA_COMPILE_OPTIONS "${_MPI_FLAG}") @@ -1459,7 +1461,7 @@ foreach(LANG IN ITEMS C CXX Fortran) set(_MPI_FIND_${LANG} TRUE) elseif( LANG IN_LIST MPI_FIND_COMPONENTS) set(_MPI_FIND_${LANG} TRUE) - elseif( "${LANG}" STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX AND MPICXX IN_LIST MPI_FIND_COMPONENTS ) + elseif( LANG STREQUAL "CXX" AND NOT MPI_CXX_SKIP_MPICXX AND MPICXX IN_LIST MPI_FIND_COMPONENTS ) set(_MPI_FIND_${LANG} TRUE) else() set(_MPI_FIND_${LANG} FALSE) @@ -1471,7 +1473,7 @@ foreach(LANG IN ITEMS C CXX Fortran) endif() endif() if(_MPI_FIND_${LANG}) - if( "${LANG}" STREQUAL "CXX" AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS ) + if( LANG STREQUAL "CXX" AND NOT MPICXX IN_LIST MPI_FIND_COMPONENTS ) option(MPI_CXX_SKIP_MPICXX "If true, the MPI-2 C++ bindings are disabled using definitions." FALSE) mark_as_advanced(MPI_CXX_SKIP_MPICXX) endif() @@ -1493,7 +1495,7 @@ foreach(LANG IN ITEMS C CXX Fortran) set(MPI_${LANG}_TRIED_IMPLICIT TRUE) endif() - if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}" OR NOT MPI_${LANG}_WORKS) + if(NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER OR NOT MPI_${LANG}_WORKS) set(MPI_${LANG}_WRAPPER_FOUND FALSE) set(MPI_PINNED_COMPILER FALSE) @@ -1529,7 +1531,7 @@ foreach(LANG IN ITEMS C CXX Fortran) DOC "MPI compiler for ${LANG}" ) - if("${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") + if(MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER) set(MPI_PINNED_COMPILER TRUE) # If we haven't made the implicit compiler test yet, perform it now. @@ -1590,7 +1592,7 @@ foreach(LANG IN ITEMS C CXX Fortran) endif() if(_MPI_PKG AND PKG_CONFIG_FOUND) pkg_check_modules("MPI_${LANG}_PKG" "${_MPI_PKG}") - if("${MPI_${LANG}_PKG_FOUND}") + if(MPI_${LANG}_PKG_FOUND) set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_${LANG}_PKG_CFLAGS} CACHE STRING "MPI ${LANG} compilation options" FORCE) set(MPI_${LANG}_INCLUDE_PATH ${MPI_${LANG}_PKG_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} include directories" FORCE) set(MPI_${LANG}_LINK_FLAGS ${MPI_${LANG}_PKG_LDFLAGS} CACHE STRING "MPI ${LANG} linker flags" FORCE) @@ -1611,10 +1613,10 @@ foreach(LANG IN ITEMS C CXX Fortran) endif() endif() - if(NOT MPI_SKIP_GUESSING AND NOT "${MPI_${LANG}_PKG_FOUND}") + if(NOT MPI_SKIP_GUESSING AND NOT MPI_${LANG}_PKG_FOUND) # For C++, we may use the settings for C. Should a given compiler wrapper for C++ not exist, but one for C does, we copy over the # settings for C. An MPI distribution that is in this situation would be IBM Platform MPI. - if("${LANG}" STREQUAL "CXX" AND MPI_C_WRAPPER_FOUND) + if(LANG STREQUAL "CXX" AND MPI_C_WRAPPER_FOUND) set(MPI_${LANG}_COMPILE_OPTIONS ${MPI_C_COMPILE_OPTIONS} CACHE STRING "MPI ${LANG} compilation options" ) set(MPI_${LANG}_COMPILE_DEFINITIONS ${MPI_C_COMPILE_DEFINITIONS} CACHE STRING "MPI ${LANG} compilation definitions" ) set(MPI_${LANG}_COMPILER_INCLUDE_DIRS ${MPI_C_INCLUDE_DIRS} CACHE STRING "MPI ${LANG} compiler wrapper include directories") @@ -1628,7 +1630,7 @@ foreach(LANG IN ITEMS C CXX Fortran) endif() endif() - if(NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") + if(NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER) _MPI_split_include_dirs(${LANG}) _MPI_assemble_include_dirs(${LANG}) else() @@ -1665,7 +1667,7 @@ foreach(LANG IN ITEMS C CXX Fortran) # If we've found MPI, then we'll perform additional analysis: Determine the MPI version, MPI library version, supported # MPI APIs (i.e. MPI-2 C++ bindings). For Fortran we also need to find specific parameters if we're under MPI-3. if(MPI_${LANG}_WORKS) - if("${LANG}" STREQUAL "CXX" AND NOT DEFINED MPI_MPICXX_FOUND) + if(LANG STREQUAL "CXX" AND NOT DEFINED MPI_MPICXX_FOUND) if(NOT MPI_CXX_SKIP_MPICXX AND NOT MPI_CXX_VALIDATE_SKIP_MPICXX) _MPI_try_staged_settings(${LANG} test_mpi MPICXX FALSE FALSE) if(MPI_RESULT_${LANG}_test_mpi_MPICXX) @@ -1689,7 +1691,7 @@ foreach(LANG IN ITEMS C CXX Fortran) # Fortran parameters, since those depend on the method of consumption. # For C++, we can always use the C bindings, and should do so, since the C++ bindings do not exist in MPI-3 # whereas the C bindings do, and the C++ bindings never offered any feature advantage over their C counterparts. - if("${LANG}" STREQUAL "Fortran") + if(LANG STREQUAL "Fortran") if(MPI_${LANG}_HAVE_F08_MODULE) set(MPI_${LANG}_HIGHEST_METHOD F08_MODULE) elseif(MPI_${LANG}_HAVE_F90_MODULE) @@ -1705,7 +1707,7 @@ foreach(LANG IN ITEMS C CXX Fortran) _MPI_try_staged_settings(${LANG} mpiver ${MPI_${LANG}_HIGHEST_METHOD} FALSE FALSE) if(MPI_RESULT_${LANG}_mpiver_${MPI_${LANG}_HIGHEST_METHOD}) file(STRINGS ${MPI_BIN_FOLDER}/mpiver_${LANG}.bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER") - if("${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*") + if(_MPI_VERSION_STRING MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*") set(MPI_${LANG}_VERSION_MAJOR "${CMAKE_MATCH_1}") set(MPI_${LANG}_VERSION_MINOR "${CMAKE_MATCH_2}") set(MPI_${LANG}_VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}") @@ -1724,12 +1726,12 @@ foreach(LANG IN ITEMS C CXX Fortran) _MPI_try_staged_settings(${LANG} fortranparam_mpi ${mpimethod} TRUE FALSE) if(MPI_RESULT_${LANG}_fortranparam_mpi_${mpimethod} AND NOT "${MPI_RUN_RESULT_${LANG}_fortranparam_mpi_${mpimethod}}" STREQUAL "FAILED_TO_RUN") - if("${MPI_RUN_OUTPUT_${LANG}_fortranparam_mpi_${mpimethod}}" MATCHES + if(MPI_RUN_OUTPUT_${LANG}_fortranparam_mpi_${mpimethod} MATCHES ".*INFO:SUBARRAYS\\[ *([TF]) *\\]-ASYNCPROT\\[ *([TF]) *\\].*") - if("${CMAKE_MATCH_1}" STREQUAL "T") + if(CMAKE_MATCH_1 STREQUAL "T") set(MPI_${LANG}_${mpimethod}_SUBARRAYS TRUE) endif() - if("${CMAKE_MATCH_2}" STREQUAL "T") + if(CMAKE_MATCH_2 STREQUAL "T") set(MPI_${LANG}_${mpimethod}_ASYNCPROT TRUE) endif() endif() @@ -1744,7 +1746,7 @@ foreach(LANG IN ITEMS C CXX Fortran) # By the MPI-2 standard, MPI_VERSION and MPI_SUBVERSION are valid for both C and C++ bindings. if(NOT DEFINED MPI_${LANG}_VERSION) file(STRINGS ${MPI_BIN_FOLDER}/test_mpi_${LANG}.bin _MPI_VERSION_STRING LIMIT_COUNT 1 REGEX "INFO:MPI-VER") - if("${_MPI_VERSION_STRING}" MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*") + if(_MPI_VERSION_STRING MATCHES ".*INFO:MPI-VER\\[([0-9]+)\\.([0-9]+)\\].*") set(MPI_${LANG}_VERSION_MAJOR "${CMAKE_MATCH_1}") set(MPI_${LANG}_VERSION_MINOR "${CMAKE_MATCH_2}") set(MPI_${LANG}_VERSION "${MPI_${LANG}_VERSION_MAJOR}.${MPI_${LANG}_VERSION_MINOR}") @@ -1764,7 +1766,7 @@ foreach(LANG IN ITEMS C CXX Fortran) if(MPI_DETERMINE_LIBRARY_VERSION AND NOT MPI_${LANG}_LIBRARY_VERSION_STRING) _MPI_try_staged_settings(${LANG} libver_mpi ${MPI_${LANG}_HIGHEST_METHOD} TRUE FALSE) if(MPI_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD} AND - "${MPI_RUN_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD}}" EQUAL "0") + MPI_RUN_RESULT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD} EQUAL "0") string(STRIP "${MPI_RUN_OUTPUT_${LANG}_libver_mpi_${MPI_${LANG}_HIGHEST_METHOD}}" MPI_${LANG}_LIBRARY_VERSION_STRING) else() @@ -1778,12 +1780,12 @@ foreach(LANG IN ITEMS C CXX Fortran) set(MPI_${LANG}_FIND_VERSION_EXACT ${MPI_FIND_VERSION_EXACT}) unset(MPI_${LANG}_REQUIRED_VARS) - if (NOT "${MPI_${LANG}_COMPILER}" STREQUAL "${CMAKE_${LANG}_COMPILER}") + if (NOT MPI_${LANG}_COMPILER STREQUAL CMAKE_${LANG}_COMPILER) foreach(mpilibname IN LISTS MPI_${LANG}_LIB_NAMES) list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${mpilibname}_LIBRARY") endforeach() list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_LIB_NAMES") - if("${LANG}" STREQUAL "Fortran") + if(LANG STREQUAL "Fortran") # For Fortran we only need one of the module or header directories to have *some* support for MPI. if(NOT MPI_${LANG}_MODULE_DIR) list(APPEND MPI_${LANG}_REQUIRED_VARS "MPI_${LANG}_F77_HEADER_DIR") @@ -1883,7 +1885,7 @@ else() endif() list(LENGTH MPI_LIBRARIES MPI_NUMLIBS) -if (MPI_NUMLIBS GREATER 1) +if (MPI_NUMLIBS GREATER "1") set(MPI_EXTRA_LIBRARY_WORK "${MPI_LIBRARIES}") list(REMOVE_AT MPI_EXTRA_LIBRARY_WORK 0) set(MPI_EXTRA_LIBRARY "${MPI_EXTRA_LIBRARY_WORK}") diff --git a/Modules/FindMatlab.cmake b/Modules/FindMatlab.cmake index 470ebe0..07a9adf 100644 --- a/Modules/FindMatlab.cmake +++ b/Modules/FindMatlab.cmake @@ -85,10 +85,18 @@ Module Input Variables Users or projects may set the following variables to configure the module behavior: +:variable:`Matlab_ROOT <<PackageName>_ROOT>` + .. versionadded:: 3.25 + + Default value for :variable:`Matlab_ROOT_DIR`, the root of the Matlab + installation. + :variable:`Matlab_ROOT_DIR` - the root of the Matlab installation. + The root of the Matlab installation. + :variable:`MATLAB_FIND_DEBUG` outputs debug information + :variable:`MATLAB_ADDITIONAL_VERSIONS` additional versions of Matlab for the automatic retrieval of the installed versions. @@ -844,6 +852,15 @@ function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_ve endif() endif() + if(NOT EXISTS "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") + # last resort check as some HPC with "module load matlab" not enacted fail to catch in earlier checks + # and error CMake configure even if find_package(Matlab) is not REQUIRED + if(MATLAB_FIND_DEBUG) + message(WARNING "[MATLAB] Unable to determine the version of Matlab. The version log file does not exist.") + endif() + return() + endif() + # if successful, read back the log file(READ "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp" _matlab_version_from_cmd) file(REMOVE "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp") @@ -1573,6 +1590,13 @@ endfunction() # this variable will get all Matlab installations found in the current system. set(_matlab_possible_roots) +if(NOT DEFINED Matlab_ROOT AND DEFINED ENV{Matlab_ROOT}) + set(Matlab_ROOT $ENV{Matlab_ROOT}) +endif() +if(DEFINED Matlab_ROOT) + set(Matlab_ROOT_DIR ${Matlab_ROOT}) +endif() + if(Matlab_ROOT_DIR) # if the user specifies a possible root, we keep this one diff --git a/Modules/FindOpenACC.cmake b/Modules/FindOpenACC.cmake index cf58f3b..00e42b8 100644 --- a/Modules/FindOpenACC.cmake +++ b/Modules/FindOpenACC.cmake @@ -27,6 +27,13 @@ The module provides :prop_tgt:`IMPORTED` targets: Variables ^^^^^^^^^ +The module defines the following variables: + +``OpenACC_FOUND`` + .. versionadded:: 3.25 + + Variable indicating that OpenACC flags for at least one languages have been found. + This module will set the following variables per language in your project, where ``<lang>`` is one of C, CXX, or Fortran: @@ -121,21 +128,18 @@ set(OpenACC_Fortran_CHECK_VERSION_SOURCE ) -function(_OPENACC_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH) - set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenACC) +macro(_OPENACC_PREPARE_SOURCE LANG CONTENT_ID NAME_PREFIX FULLNAME_VAR CONTENT_VAR) if("${LANG}" STREQUAL "C") - set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c") - file(WRITE "${SRC_FILE}" "${OpenACC_C_CXX_${SRC_FILE_CONTENT_VAR}}") + set(${FULLNAME_VAR} "${NAME_PREFIX}.c") + set(${CONTENT_VAR} "${OpenACC_C_CXX_${CONTENT_ID}}") elseif("${LANG}" STREQUAL "CXX") - set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp") - file(WRITE "${SRC_FILE}" "${OpenACC_C_CXX_${SRC_FILE_CONTENT_VAR}}") + set(${FULLNAME_VAR} "${NAME_PREFIX}.cpp") + set(${CONTENT_VAR} "${OpenACC_C_CXX_${CONTENT_ID}}") elseif("${LANG}" STREQUAL "Fortran") - set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.F90") - file(WRITE "${SRC_FILE}_in" "${OpenACC_Fortran_${SRC_FILE_CONTENT_VAR}}") - configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY) + set(${FULLNAME_VAR} "${NAME_PREFIX}.F90") + set(${CONTENT_VAR} "${OpenACC_Fortran_${CONTENT_ID}}") endif() - set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE) -endfunction() +endmacro() function(_OPENACC_GET_FLAGS_CANDIDATE LANG FLAG_VAR) @@ -177,10 +181,12 @@ endfunction() function(_OPENACC_GET_FLAGS LANG FLAG_VAR) set(FLAG_CANDIDATES "") _OPENACC_GET_FLAGS_CANDIDATE("${LANG}" FLAG_CANDIDATES) - _OPENACC_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenACCTryFlag _OPENACC_TEST_SRC) + _OPENACC_PREPARE_SOURCE("${LANG}" TEST_SOURCE OpenACCTryFlag + _OPENACC_TEST_SRC_NAME _OPENACC_TEST_SRC_CONTENT) foreach(FLAG IN LISTS FLAG_CANDIDATES) - try_compile(OpenACC_FLAG_TEST_RESULT ${CMAKE_BINARY_DIR} ${_OPENACC_TEST_SRC} + try_compile(OpenACC_FLAG_TEST_RESULT + SOURCE_FROM_VAR "${_OPENACC_TEST_SRC_NAME}" _OPENACC_TEST_SRC_CONTENT CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${FLAG}" OUTPUT_VARIABLE OpenACC_TRY_COMPILE_OUTPUT ) @@ -205,13 +211,15 @@ endfunction() function(_OPENACC_GET_SPEC_DATE LANG SPEC_DATE) - _OPENACC_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenACCCheckVersion _OPENACC_TEST_SRC) + _OPENACC_PREPARE_SOURCE(${LANG} CHECK_VERSION_SOURCE OpenACCCheckVersion + _OPENACC_TEST_SRC_NAME _OPENACC_TEST_SRC_CONTENT) set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenACC/accver_${LANG}.bin") - try_compile(OpenACC_SPECTEST_${LANG} "${CMAKE_BINARY_DIR}" "${_OPENACC_TEST_SRC}" - CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenACC_${LANG}_FLAGS}" - COPY_FILE ${BIN_FILE} - OUTPUT_VARIABLE OUTPUT) + try_compile(OpenACC_SPECTEST_${LANG} + SOURCE_FROM_VAR "${_OPENACC_TEST_SRC_NAME}" _OPENACC_TEST_SRC_CONTENT + CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenACC_${LANG}_FLAGS}" + COPY_FILE "${BIN_FILE}" + OUTPUT_VARIABLE OUTPUT) if(${OpenACC_SPECTEST_${LANG}}) file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenACC-date") @@ -270,6 +278,9 @@ foreach (LANG IN ITEMS C CXX Fortran) REQUIRED_VARS OpenACC_${LANG}_FLAGS VERSION_VAR OpenACC_${LANG}_VERSION ) + if(OpenACC_${LANG}_FOUND) + set(OpenACC_FOUND TRUE) + endif() endif() endforeach() diff --git a/Modules/FindOpenAL.cmake b/Modules/FindOpenAL.cmake index b5b92c5..53aafdc 100644 --- a/Modules/FindOpenAL.cmake +++ b/Modules/FindOpenAL.cmake @@ -29,6 +29,16 @@ OpenAL is searched in the following order: 5. Manually compiled framework: ``/Library/Frameworks``. 6. Add-on package: ``/opt``. +IMPORTED Targets +^^^^^^^^^^^^^^^^ + +.. versionadded:: 3.25 + +This module defines the :prop_tgt:`IMPORTED` target: + +``OpenAL::OpenAL`` + The OpenAL library, if found. + Result Variables ^^^^^^^^^^^^^^^^ @@ -94,3 +104,19 @@ find_package_handle_standard_args( ) mark_as_advanced(OPENAL_LIBRARY OPENAL_INCLUDE_DIR) + +if(OPENAL_INCLUDE_DIR AND OPENAL_LIBRARY) + if(NOT TARGET OpenAL::OpenAL) + if(EXISTS "${OPENAL_LIBRARY}") + add_library(OpenAL::OpenAL UNKNOWN IMPORTED) + set_target_properties(OpenAL::OpenAL PROPERTIES + IMPORTED_LOCATION "${OPENAL_LIBRARY}") + else() + add_library(OpenAL::OpenAL INTERFACE IMPORTED) + set_target_properties(OpenAL::OpenAL PROPERTIES + IMPORTED_LIBNAME "${OPENAL_LIBRARY}") + endif() + set_target_properties(OpenAL::OpenAL PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${OPENAL_INCLUDE_DIR}") + endif() +endif() diff --git a/Modules/FindOpenGL.cmake b/Modules/FindOpenGL.cmake index d6d1c00..a9a1b2a 100644 --- a/Modules/FindOpenGL.cmake +++ b/Modules/FindOpenGL.cmake @@ -377,7 +377,7 @@ else() (NOT OPENGL_USE_EGL AND NOT OPENGL_glx_LIBRARY AND OPENGL_gl_LIBRARY)) - list(APPEND _OpenGL_REQUIRED_VARS OPENGL_gl_LIBRARY) + list(PREPEND _OpenGL_REQUIRED_VARS OPENGL_gl_LIBRARY) endif() # We always need the 'gl.h' include dir. diff --git a/Modules/FindOpenMP.cmake b/Modules/FindOpenMP.cmake index ecfb7f9..9e24925 100644 --- a/Modules/FindOpenMP.cmake +++ b/Modules/FindOpenMP.cmake @@ -178,27 +178,25 @@ set(OpenMP_Fortran_TEST_SOURCE " ) -function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH) - set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP) +macro(_OPENMP_PREPARE_SOURCE LANG CONTENT_ID NAME_PREFIX FULLNAME_VAR CONTENT_VAR) if("${LANG}" STREQUAL "C") - set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c") - file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}") + set(${FULLNAME_VAR} "${NAME_PREFIX}.c") + set(${CONTENT_VAR} "${OpenMP_C_CXX_${CONTENT_ID}}") elseif("${LANG}" STREQUAL "CXX") - set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp") - file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}") + set(${FULLNAME_VAR} "${NAME_PREFIX}.cpp") + set(${CONTENT_VAR} "${OpenMP_C_CXX_${CONTENT_ID}}") elseif("${LANG}" STREQUAL "Fortran") - set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90") - file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}") - configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY) + set(${FULLNAME_VAR} "${NAME_PREFIX}.F90") + string(CONFIGURE "${OpenMP_Fortran_${CONTENT_ID}}" ${CONTENT_VAR} @ONLY) endif() - set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE) -endfunction() +endmacro() include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseImplicitLinkInfo.cmake) function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) _OPENMP_FLAG_CANDIDATES("${LANG}") - _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC) + _OPENMP_PREPARE_SOURCE("${LANG}" TEST_SOURCE OpenMPTryFlag + _OPENMP_TEST_SRC_NAME _OPENMP_TEST_SRC_CONTENT) unset(OpenMP_VERBOSE_COMPILE_OPTIONS) separate_arguments(OpenMP_VERBOSE_OPTIONS NATIVE_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}") @@ -214,7 +212,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}") endif() string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}") - try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} + try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} + SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT @@ -238,11 +237,29 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) OpenMP_${LANG}_IMPLICIT_FWK_DIRS OpenMP_${LANG}_LOG_VAR "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}" + LANGUAGE ${LANG} ) file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n") + # For LCC we should additionally alanyze -print-search-dirs output + # to check for additional implicit_dirs. + # Note: This won't work if CMP0129 policy is set to OLD! + if("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "LCC") + execute_process( + COMMAND ${CMAKE_${LANG}_COMPILER} -print-search-dirs + OUTPUT_VARIABLE output_lines + COMMAND_ERROR_IS_FATAL ANY + ERROR_QUIET) + if("${output_lines}" MATCHES ".*\nlibraries:[ \t]+(.*:)\n.*") + string(REPLACE ":" ";" implicit_dirs_addon "${CMAKE_MATCH_1}") + list(PREPEND OpenMP_${LANG}_IMPLICIT_LINK_DIRS ${implicit_dirs_addon}) + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + " Extended OpenMP library search paths: [${implicit_dirs}]\n") + endif() + endif() + unset(_OPENMP_LIB_NAMES) foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES) get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY) @@ -262,7 +279,9 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP" HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS} CMAKE_FIND_ROOT_PATH_BOTH - NO_DEFAULT_PATH + NO_PACKAGE_ROOT_PATH + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH ) endif() mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY) @@ -291,7 +310,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) # Try without specifying include directory first. We only want to # explicitly add a search path if the header can't be found on the # default header search path already. - try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} + try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} + SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT @@ -301,7 +321,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) mark_as_advanced(OpenMP_${LANG}_INCLUDE_DIR) set(OpenMP_${LANG}_INCLUDE_DIR "${OpenMP_${LANG}_INCLUDE_DIR}" PARENT_SCOPE) if(OpenMP_${LANG}_INCLUDE_DIR) - try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} + try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} + SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}" LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} @@ -323,7 +344,8 @@ function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) ) mark_as_advanced(OpenMP_libomp_LIBRARY) if(OpenMP_libomp_LIBRARY) - try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} + try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} + SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT @@ -385,7 +407,8 @@ set(OpenMP_Fortran_CHECK_VERSION_SOURCE ") function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE) - _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC) + _OPENMP_PREPARE_SOURCE("${LANG}" CHECK_VERSION_SOURCE OpenMPCheckVersion + _OPENMP_TEST_SRC_NAME _OPENMP_TEST_SRC_CONTENT) unset(_includeDirFlags) if(OpenMP_${LANG}_INCLUDE_DIR) @@ -394,10 +417,11 @@ function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE) set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin") string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}") - try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}" - CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}" ${_includeDirFlags} - COPY_FILE ${BIN_FILE} - OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT) + try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} + SOURCE_FROM_VAR "${_OPENMP_TEST_SRC_NAME}" _OPENMP_TEST_SRC_CONTENT + CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}" ${_includeDirFlags} + COPY_FILE "${BIN_FILE}" + OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT) if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}}) file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date") @@ -460,10 +484,14 @@ foreach(LANG IN ITEMS C CXX) if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND" OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND") _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK) - set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}" - CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE) - set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}" - CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE) + if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND") + set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}" + CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE) + endif() + if(NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND") + set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}" + CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE) + endif() mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES) endif() endif() @@ -479,10 +507,14 @@ if(CMAKE_Fortran_COMPILER_LOADED) set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "") endif() - set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" - CACHE STRING "Fortran compiler flags for OpenMP parallelization") - set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}" - CACHE STRING "Fortran compiler libraries for OpenMP parallelization") + if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND") + set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" + CACHE STRING "Fortran compiler flags for OpenMP parallelization" FORCE) + endif() + if(NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND") + set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}" + CACHE STRING "Fortran compiler libraries for OpenMP parallelization" FORCE) + endif() mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES) endif() @@ -495,11 +527,14 @@ if(CMAKE_Fortran_COMPILER_LOADED) set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "") endif() - set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" - CACHE STRING "Fortran compiler flags for OpenMP parallelization") - - set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}" - CACHE STRING "Fortran compiler libraries for OpenMP parallelization") + if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND") + set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" + CACHE STRING "Fortran compiler flags for OpenMP parallelization" FORCE) + endif() + if(NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND") + set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}" + CACHE STRING "Fortran compiler libraries for OpenMP parallelization" FORCE) + endif() endif() if(OpenMP_Fortran_HAVE_OMPLIB_MODULE) @@ -571,7 +606,8 @@ foreach(LANG IN LISTS OpenMP_FINDLIST) separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}") set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:${LANG}>:${_OpenMP_${LANG}_OPTIONS}>") - if(CMAKE_${LANG}_COMPILER_ID STREQUAL "Fujitsu") + if(CMAKE_${LANG}_COMPILER_ID STREQUAL "Fujitsu" + OR ${CMAKE_${LANG}_COMPILER_ID} STREQUAL "IntelLLVM") set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY INTERFACE_LINK_OPTIONS "${OpenMP_${LANG}_FLAGS}") endif() diff --git a/Modules/FindOpenSP.cmake b/Modules/FindOpenSP.cmake new file mode 100644 index 0000000..655dd65 --- /dev/null +++ b/Modules/FindOpenSP.cmake @@ -0,0 +1,155 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindOpenSP +---------- + +.. versionadded:: 3.25 + +Try to find the OpenSP library. + +Result Variables +^^^^^^^^^^^^^^^^ + +This will define the following variables: + +``OpenSP_FOUND`` + True if (the requested version of) ``OpenSP`` is available + +``OpenSP_VERSION`` + The version of ``OpenSP`` + +``OpenSP_VERSION_MAJOR`` + The major version of ``OpenSP`` + +``OpenSP_VERSION_MINOR`` + The minor version of ``OpenSP`` + +``OpenSP_VERSION_PATCH`` + The patch version of ``OpenSP`` + +``OpenSP_INCLUDE_DIRS`` + The include dirs of ``OpenSP`` with its headers + +``OpenSP_LIBRARIES`` + The OpenSP library for use with target_link_libraries(). + This can be passed to target_link_libraries() instead of + the :prop_tgt:`IMPORTED` ``OpenSP::OpenSP`` target + +``OpenSP_MULTI_BYTE`` + True if ``SP_MULTI_BYTE`` was found to be defined in OpenSP's ``config.h`` + header file, which indicates that the ``OpenSP`` library was compiled with + support for multi-byte characters. The consuming target needs to define the + ``SP_MULTI_BYTE`` to match this value in order to avoid issues with character + decoding. + +IMPORTED Targets +^^^^^^^^^^^^^^^^ + +This module defines the :prop_tgt:`IMPORTED` target ``OpenSP::OpenSP``, if +OpenSP has been found. + +Cache variables +^^^^^^^^^^^^^^^ + +The following cache variables may also be set: + +``OpenSP_INCLUDE_DIR`` + the OpenSP include directory + +``OpenSP_LIBRARY`` + the absolute path of the osp library + +#]=======================================================================] + +if (NOT OpenSP_INCLUDE_DIR AND NOT OpenSP_LIBRARY) + find_package(PkgConfig) + if (PkgConfig_FOUND) + pkg_check_modules(OpenSP IMPORTED_TARGET GLOBAL opensp) + + if (OpenSP_FOUND) + add_library(OpenSP::OpenSP INTERFACE IMPORTED) + target_link_libraries(OpenSP::OpenSP INTERFACE PkgConfig::OpenSP) + + set(OpenSP_INCLUDE_DIR ${OpenSP_INCLUDE_DIRS}) + set(OpenSP_LIBRARY ${OpenSP_LIBRARIES}) + endif () + endif () +endif () + +if (NOT OpenSP_INCLUDE_DIR) + find_path(OpenSP_INCLUDE_DIR + NAMES ParserEventGeneratorKit.h + PATH_SUFFIXES OpenSP opensp + DOC "The OpenSP include directory" + ) +endif () + +if (NOT OpenSP_LIBRARY) + find_library(OpenSP_LIBRARY_RELEASE + NAMES osp libosp opensp libopensp sp133 libsp + ) + + find_library(OpenSP_LIBRARY_DEBUG + NAMES ospd libospd openspd libopenspd sp133d libspd + ) + + include(SelectLibraryConfigurations) + select_library_configurations(OpenSP) +endif () + +if (OpenSP_INCLUDE_DIR AND OpenSP_LIBRARY) + if (EXISTS "${OpenSP_INCLUDE_DIR}/config.h") + if (NOT OpenSP_VERSION) + file(STRINGS "${OpenSP_INCLUDE_DIR}/config.h" opensp_version_str REGEX "^#define[\t ]+SP_VERSION[\t ]+\".*\"") + string(REGEX REPLACE "^.*SP_VERSION[\t ]+\"([^\"]*)\".*$" "\\1" OpenSP_VERSION "${opensp_version_str}") + unset(opensp_version_str) + endif () + + if (OpenSP_VERSION MATCHES [=[([0-9]+)\.([0-9]+)\.([0-9]+)]=]) + set(OpenSP_VERSION_MAJOR "${CMAKE_MATCH_1}") + set(OpenSP_VERSION_MINOR "${CMAKE_MATCH_2}") + set(OpenSP_VERSION_PATCH "${CMAKE_MATCH_3}") + endif () + + include(CheckCXXSymbolExists) + check_cxx_symbol_exists(SP_MULTI_BYTE "${OpenSP_INCLUDE_DIR}/config.h" OpenSP_MULTI_BYTE) + endif () + + if (NOT TARGET OpenSP::OpenSP) + set(OpenSP_INCLUDE_DIRS ${OpenSP_INCLUDE_DIR}) + + add_library(OpenSP::OpenSP UNKNOWN IMPORTED) + set_target_properties(OpenSP::OpenSP PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${OpenSP_INCLUDE_DIRS}") + + if (OpenSP_LIBRARY_RELEASE) + set_target_properties(OpenSP::OpenSP PROPERTIES IMPORTED_LOCATION_RELEASE "${OpenSP_LIBRARY_RELEASE}") + set_property(TARGET OpenSP::OpenSP APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) + endif () + + if (OpenSP_LIBRARY_DEBUG) + set_target_properties(OpenSP::OpenSP PROPERTIES IMPORTED_LOCATION_DEBUG "${OpenSP_LIBRARY_DEBUG}") + set_property(TARGET OpenSP::OpenSP APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) + endif () + + if (NOT OpenSP_LIBRARY_RELEASE AND NOT OpenSP_LIBRARY_DEBUG) + set_property(TARGET OpenSP::OpenSP APPEND PROPERTY IMPORTED_LOCATION "${OpenSP_LIBRARY}") + endif () + endif () +endif () + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OpenSP + FOUND_VAR OpenSP_FOUND + REQUIRED_VARS OpenSP_LIBRARY OpenSP_INCLUDE_DIR + VERSION_VAR OpenSP_VERSION + ) + +mark_as_advanced(OpenSP_INCLUDE_DIR OpenSP_LIBRARY OpenSP_MULTI_BYTE) + +include(FeatureSummary) +set_package_properties(OpenSP PROPERTIES + URL "http://openjade.sourceforge.net/doc/index.htm" + DESCRIPTION "An SGML System Conforming to International Standard ISO 8879" + ) diff --git a/Modules/FindOpenSSL.cmake b/Modules/FindOpenSSL.cmake index 9278566..352c4cc 100644 --- a/Modules/FindOpenSSL.cmake +++ b/Modules/FindOpenSSL.cmake @@ -90,13 +90,25 @@ This module will set the following variables in your project: Hints ^^^^^ -Set ``OPENSSL_ROOT_DIR`` to the root directory of an OpenSSL installation. +The following variables may be set to control search behavior: -.. versionadded:: 3.4 - Set ``OPENSSL_USE_STATIC_LIBS`` to ``TRUE`` to look for static libraries. +``OPENSSL_ROOT_DIR`` + Set to the root directory of an OpenSSL installation. + +``OPENSSL_USE_STATIC_LIBS`` + .. versionadded:: 3.4 + + Set to ``TRUE`` to look for static libraries. + +``OPENSSL_MSVC_STATIC_RT`` + .. versionadded:: 3.5 + + Set to ``TRUE`` to choose the MT version of the lib. -.. versionadded:: 3.5 - Set ``OPENSSL_MSVC_STATIC_RT`` set ``TRUE`` to choose the MT version of the lib. +``ENV{PKG_CONFIG_PATH}`` + On UNIX-like systems, ``pkg-config`` is used to locate the system OpenSSL. + Set the ``PKG_CONFIG_PATH`` environment varialbe to look in alternate + locations. Useful on multi-lib systems. #]=======================================================================] macro(_OpenSSL_test_and_find_dependencies ssl_library crypto_library) diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake index fbcf7cd..56ba1e6 100644 --- a/Modules/FindPackageHandleStandardArgs.cmake +++ b/Modules/FindPackageHandleStandardArgs.cmake @@ -535,18 +535,24 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG) set(VERSION_MSG "") set(VERSION_OK TRUE) - # check with DEFINED here as the requested or found version may be "0" + # check that the version variable is not empty to avoid emitting a misleading + # message (i.e. `Found unsuitable version ""`) if (DEFINED ${_NAME}_FIND_VERSION) if(DEFINED ${FPHSA_VERSION_VAR}) - set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}}) - if (FPHSA_HANDLE_VERSION_RANGE) - set (FPCV_HANDLE_VERSION_RANGE HANDLE_VERSION_RANGE) + if(NOT "${${FPHSA_VERSION_VAR}}" STREQUAL "") + set(_FOUND_VERSION ${${FPHSA_VERSION_VAR}}) + if (FPHSA_HANDLE_VERSION_RANGE) + set (FPCV_HANDLE_VERSION_RANGE HANDLE_VERSION_RANGE) + else() + set(FPCV_HANDLE_VERSION_RANGE NO_AUTHOR_WARNING_VERSION_RANGE) + endif() + find_package_check_version ("${_FOUND_VERSION}" VERSION_OK RESULT_MESSAGE_VARIABLE VERSION_MSG + ${FPCV_HANDLE_VERSION_RANGE}) else() - set(FPCV_HANDLE_VERSION_RANGE NO_AUTHOR_WARNING_VERSION_RANGE) + set(VERSION_OK FALSE) endif() - find_package_check_version ("${_FOUND_VERSION}" VERSION_OK RESULT_MESSAGE_VARIABLE VERSION_MSG - ${FPCV_HANDLE_VERSION_RANGE}) - else() + endif() + if("${${FPHSA_VERSION_VAR}}" STREQUAL "") # if the package was not found, but a version was given, add that to the output: if(${_NAME}_FIND_VERSION_EXACT) set(VERSION_MSG "(Required is exact version \"${${_NAME}_FIND_VERSION}\")") diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index c4fae6b..7a127e4 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -14,6 +14,8 @@ cmake_policy(PUSH) cmake_policy (SET CMP0012 NEW) # IN_LIST operator cmake_policy (SET CMP0057 NEW) +# registry view behavior +cmake_policy (SET CMP0134 NEW) if (NOT DEFINED _PYTHON_PREFIX) message (FATAL_ERROR "FindPython: INTERNAL ERROR") @@ -175,30 +177,31 @@ function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS) foreach (version IN LISTS _PGR_VERSION) string (REPLACE "." "" version_no_dots ${version}) list (APPEND registries - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]) + [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath] + [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]) if (version VERSION_GREATER_EQUAL "3.5") + # cmake_host_system_information is not usable in bootstrap get_filename_component (arch "[HKEY_CURRENT_USER\\Software\\Python\\PythonCore\\${version};SysArchitecture]" NAME) if (arch MATCHES "(${_${_PYTHON_PREFIX}_ARCH}|${_${_PYTHON_PREFIX}_ARCH2})bit") list (APPEND registries - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath]) + [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath]) endif() else() list (APPEND registries - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath]) + [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath]) endif() list (APPEND registries - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] - [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath] - [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]) + [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath] + [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath] + [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath] + [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath] + [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}/InstallPath] + [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath] + [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]) endforeach() elseif (implementation STREQUAL "IronPython") foreach (version IN LISTS _PGR_VERSION) - list (APPEND registries [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${version}\\InstallPath]) + list (APPEND registries [HKEY_LOCAL_MACHINE/SOFTWARE/IronPython/${version}/InstallPath]) endforeach() endif() endforeach() @@ -711,7 +714,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) if (_PVI_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_EXECUTABLE}") # interpreter does not exist anymore - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -732,7 +735,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) endif() if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -748,7 +751,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result) # interpreter is not usable - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -773,7 +776,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) if (_PVI_EXACT AND NOT version VERSION_EQUAL _PVI_VERSION) # interpreter has wrong version - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() else() @@ -782,7 +785,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${_PVI_VERSION}") if (NOT major_version VERSION_EQUAL expected_major_version OR NOT version VERSION_GREATER_EQUAL _PVI_VERSION) - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -794,7 +797,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) find_package_check_version ("${version}" in_range HANDLE_VERSION_RANGE) if (NOT in_range) # interpreter has invalid version - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() @@ -813,9 +816,9 @@ function (_PYTHON_VALIDATE_INTERPRETER) if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # interpreter not usable or has wrong major version if (result) - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") else() - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") endif() set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() @@ -836,9 +839,9 @@ function (_PYTHON_VALIDATE_INTERPRETER) if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P) # interpreter not usable or has wrong architecture if (result) - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") else() - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") endif() set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() @@ -846,6 +849,14 @@ function (_PYTHON_VALIDATE_INTERPRETER) endif() endfunction() +function(_python_validate_find_interpreter status interpreter) + set(_${_PYTHON_PREFIX}_EXECUTABLE "${interpreter}" CACHE FILEPATH "" FORCE) + _python_validate_interpreter (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + if (NOT _${_PYTHON_PREFIX}_EXECUTABLE) + set (${status} FALSE PARENT_SCOPE) + endif() +endfunction() + function (_PYTHON_VALIDATE_COMPILER) if (NOT _${_PYTHON_PREFIX}_COMPILER) @@ -856,7 +867,7 @@ function (_PYTHON_VALIDATE_COMPILER) if (_PVC_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_COMPILER}") # Compiler does not exist anymore - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") return() endif() @@ -883,7 +894,7 @@ function (_PYTHON_VALIDATE_COMPILER) file (REMOVE_RECURSE "${working_dir}") if (result) # compiler is not usable - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") return() endif() @@ -909,7 +920,7 @@ function (_PYTHON_VALIDATE_COMPILER) if (_PVC_EXACT AND NOT version VERSION_EQUAL _PVC_VERSION) # interpreter has wrong version - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") return() else() @@ -918,7 +929,7 @@ function (_PYTHON_VALIDATE_COMPILER) string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${_PVC_VERSION}") if (NOT major_version VERSION_EQUAL expected_major_version OR NOT version VERSION_GREATER_EQUAL _PVC_VERSION) - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") return() endif() @@ -930,7 +941,7 @@ function (_PYTHON_VALIDATE_COMPILER) find_package_check_version ("${version}" in_range HANDLE_VERSION_RANGE) if (NOT in_range) # interpreter has invalid version - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") return() endif() @@ -939,13 +950,21 @@ function (_PYTHON_VALIDATE_COMPILER) string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" major_version "${version}") if (NOT major_version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # Compiler has wrong major version - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong major version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Wrong major version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") return() endif() endif() endfunction() +function(_python_validate_find_compiler status compiler) + set(_${_PYTHON_PREFIX}_COMPILER "${compiler}" CACHE FILEPATH "" FORCE) + _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + if (NOT _${_PYTHON_PREFIX}_COMPILER) + set (${status} FALSE PARENT_SCOPE) + endif() +endfunction() + function (_PYTHON_VALIDATE_LIBRARY) if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) @@ -957,7 +976,7 @@ function (_PYTHON_VALIDATE_LIBRARY) if (_PVL_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") # library does not exist anymore - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") if (WIN32) set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND") @@ -971,7 +990,7 @@ function (_PYTHON_VALIDATE_LIBRARY) if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT lib_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") else() if (_PVL_VERSION OR _PVL_IN_RANGE) @@ -980,7 +999,7 @@ function (_PYTHON_VALIDATE_LIBRARY) string (REGEX MATCH "[0-9](\\.[0-9]+)?" version "${_PVL_VERSION}") if ((_PVL_EXACT AND NOT lib_VERSION VERSION_EQUAL version) OR (lib_VERSION VERSION_LESS version)) # library has wrong version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") endif() endif() @@ -990,14 +1009,14 @@ function (_PYTHON_VALIDATE_LIBRARY) find_package_check_version ("${lib_VERSION}" in_range HANDLE_VERSION_RANGE) if (NOT in_range) # library has wrong version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") endif() endif() else() if (NOT lib_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # library has wrong major version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") endif() endif() @@ -1023,7 +1042,7 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR) if (_PVID_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") # include file does not exist anymore - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") return() endif() @@ -1033,14 +1052,14 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR) if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT inc_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") else() if (_PVID_VERSION OR _PVID_IN_RANGE) if (_PVID_VERSION) if ((_PVID_EXACT AND NOT inc_VERSION VERSION_EQUAL expected_version) OR (inc_VERSION VERSION_LESS expected_version)) # include dir has wrong version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() endif() @@ -1050,14 +1069,14 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR) find_package_check_version ("${inc_VERSION}" in_range HANDLE_VERSION_RANGE) if (NOT in_range) # include dir has wrong version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() endif() else() if (NOT inc_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # include dir has wrong major version - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE) + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() endif() @@ -1247,12 +1266,14 @@ if (DEFINED ${_PYTHON_PREFIX}_FIND_STRATEGY) endif() # Python and Anaconda distributions: define which architectures can be used +unset (_${_PYTHON_PREFIX}_REGISTRY_VIEW) if (CMAKE_SIZEOF_VOID_P) math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8") if ("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # In this case, search only for 64bit or 32bit set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH}) + set (_${_PYTHON_PREFIX}_REGISTRY_VIEW REGISTRY_VIEW ${_${_PYTHON_PREFIX}_ARCH}) else() if (_${_PYTHON_PREFIX}_ARCH EQUAL "32") set (_${_PYTHON_PREFIX}_ARCH2 64) @@ -1506,9 +1527,13 @@ endfunction() unset (_${_PYTHON_PREFIX}_REQUIRED_VARS) unset (_${_PYTHON_PREFIX}_CACHED_VARS) unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE) +set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE CACHE INTERNAL "Interpreter reason failure") unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE) +set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE CACHE INTERNAL "Compiler reason failure") unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE) +set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE CACHE INTERNAL "Development reason failure") unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE) +set (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE CACHE INTERNAL "NumPy reason failure") # preamble @@ -1590,9 +1615,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - - _python_validate_interpreter (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1612,8 +1636,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1626,9 +1650,10 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) HINTS ${_${_PYTHON_PREFIX}_HINTS} PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} + ${_${_PYTHON_PREFIX}_REGISTRY_VIEW} NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1641,8 +1666,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) HINTS ${_${_PYTHON_PREFIX}_HINTS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1650,8 +1675,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} NAMES_PER_DIR - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}) - _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1663,8 +1688,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_DEFAULT_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_DEFAULT_PATH + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1676,8 +1701,9 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_DEFAULT_PATH) - _python_validate_interpreter (${${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + ${_${_PYTHON_PREFIX}_REGISTRY_VIEW} + NO_DEFAULT_PATH + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1687,9 +1713,9 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endwhile() else() # look-up for various versions and locations - set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS EXACT) + set (_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS EXACT) if (${_PYTHON_PREFIX}_FIND_VERSION_RANGE) - list (APPEND _${_PYTHON_PREFIX}_VALIDATE_OPTIONS IN_RANGE) + list (APPEND _${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS IN_RANGE) endif() foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) @@ -1698,6 +1724,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS VERSION ${_${_PYTHON_PREFIX}_VERSION}) _python_get_registries (_${_PYTHON_PREFIX}_REGISTRY_PATHS VERSION ${_${_PYTHON_PREFIX}_VERSION}) + set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS}) # Virtual environments handling if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") @@ -1710,8 +1737,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1731,7 +1758,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_interpreter) endif() # Windows registry @@ -1742,11 +1770,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) HINTS ${_${_PYTHON_PREFIX}_HINTS} PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} + ${_${_PYTHON_PREFIX}_REGISTRY_VIEW} NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_interpreter) endif() - _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1758,21 +1787,18 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) HINTS ${_${_PYTHON_PREFIX}_HINTS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() + # try using standard paths. - # NAMES_PER_DIR is not defined on purpose to have a chance to find - # expected version. - # For example, typical systems have 'python' for version 2.* and 'python3' - # for version 3.*. So looking for names per dir will find, potentially, - # systematically 'python' (i.e. version 2) even if version 3 is searched. find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}) - _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NAMES_PER_DIR + PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} + VALIDATOR _python_validate_find_interpreter) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1784,7 +1810,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_DEFAULT_PATH) + NO_DEFAULT_PATH + VALIDATOR _python_validate_find_interpreter) endif() # Windows registry @@ -1794,10 +1821,11 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_DEFAULT_PATH) + ${_${_PYTHON_PREFIX}_REGISTRY_VIEW} + NO_DEFAULT_PATH + VALIDATOR _python_validate_find_interpreter) endif() - _python_validate_interpreter (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() @@ -1806,15 +1834,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) if (NOT _${_PYTHON_PREFIX}_EXECUTABLE AND NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY") # No specific version found. Retry with generic names and standard paths. - # NAMES_PER_DIR is not defined on purpose to have a chance to find - # expected version. - # For example, typical systems have 'python' for version 2.* and 'python3' - # for version 3.*. So looking for names per dir will find, potentially, - # systematically 'python' (i.e. version 2) even if version 3 is searched. _python_get_names (_${_PYTHON_PREFIX}_NAMES POSIX INTERPRETER) + unset (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS) find_program (_${_PYTHON_PREFIX}_EXECUTABLE - NAMES ${_${_PYTHON_PREFIX}_NAMES}) - _python_validate_interpreter () + NAMES ${_${_PYTHON_PREFIX}_NAMES} + NAMES_PER_DIR + VALIDATOR _python_validate_find_interpreter) endif() endif() endif() @@ -1836,7 +1861,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # Interpreter is not usable set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE FALSE) unset (${_PYTHON_PREFIX}_VERSION) - set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot run the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot run the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") endif() endif() @@ -1884,7 +1909,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() if (${_PYTHON_PREFIX}_Interpreter_FOUND) - unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE) + unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE CACHE) # compute and save interpreter signature string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_EXECUTABLE}") @@ -2058,8 +2083,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2072,9 +2097,10 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} + ${_${_PYTHON_PREFIX}_REGISTRY_VIEW} NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2087,8 +2113,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2097,8 +2123,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) find_program (_${_PYTHON_PREFIX}_COMPILER NAMES ${_${_PYTHON_PREFIX}_COMPILER_NAMES} NAMES_PER_DIR - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}) - _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2110,12 +2136,13 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_DEFAULT_PATH) - _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_DEFAULT_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() endif() + # Windows registry if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") find_program (_${_PYTHON_PREFIX}_COMPILER @@ -2123,8 +2150,9 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_DEFAULT_PATH) - _python_validate_compiler (${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + ${_${_PYTHON_PREFIX}_REGISTRY_VIEW} + NO_DEFAULT_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2134,9 +2162,9 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endwhile() else() # try using root dir and registry - set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS EXACT) + set (_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS EXACT) if (${_PYTHON_PREFIX}_FIND_VERSION_RANGE) - list (APPEND _${_PYTHON_PREFIX}_VALIDATE_OPTIONS IN_RANGE) + list (APPEND _${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS IN_RANGE) endif() foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) @@ -2157,6 +2185,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) IMPLEMENTATIONS IronPython VERSION ${_${_PYTHON_PREFIX}_VERSION}) + set (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_COMMON_VALIDATE_OPTIONS}) + # Apple frameworks handling if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") find_program (_${_PYTHON_PREFIX}_COMPILER @@ -2168,8 +2198,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2182,9 +2212,10 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} + ${_${_PYTHON_PREFIX}_REGISTRY_VIEW} NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2197,8 +2228,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_SYSTEM_PATH) - _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_CMAKE_SYSTEM_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2210,8 +2241,8 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_DEFAULT_PATH) - _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + NO_DEFAULT_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2223,8 +2254,9 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} - NO_DEFAULT_PATH) - _python_validate_compiler (VERSION ${_${_PYTHON_PREFIX}_VERSION} ${_${_PYTHON_PREFIX}_VALIDATE_OPTIONS}) + ${_${_PYTHON_PREFIX}_REGISTRY_VIEW} + NO_DEFAULT_PATH + VALIDATOR _python_validate_find_compiler) if (_${_PYTHON_PREFIX}_COMPILER) break() endif() @@ -2240,11 +2272,13 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) IMPLEMENTATIONS IronPython VERSION ${_${_PYTHON_PREFIX}_FIND_VERSIONS} COMPILER) + unset (_${_PYTHON_PREFIX}_VALIDATE_OPTIONS) find_program (_${_PYTHON_PREFIX}_COMPILER NAMES ${_${_PYTHON_PREFIX}_COMPILER_NAMES} + NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} - PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}) - _python_validate_compiler () + PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES} + VALIDATOR _python_validate_find_compiler) endif() endif() @@ -2285,7 +2319,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) else() # compiler not usable set (_${_PYTHON_PREFIX}_COMPILER_USABLE FALSE) - set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot run the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") + set_property (CACHE _${_PYTHON_PREFIX}_Compiler_REASON_FAILURE PROPERTY VALUE "Cannot run the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"") endif() file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}") endif() @@ -2304,7 +2338,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() if (${_PYTHON_PREFIX}_Compiler_FOUND) - unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE) + unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE CACHE) # compute and save compiler signature string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_COMPILER}") @@ -2786,7 +2820,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS set (${_PYTHON_PREFIX}_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"") set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") endif() @@ -2837,7 +2871,15 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) while (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) - if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS + set (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED TRUE) + foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Module Embed) + string (TOUPPER "${_${_PYTHON_PREFIX}_COMPONENT}" _${_PYTHON_PREFIX}_ID) + if ("Development.${_${_PYTHON_PREFIX}_COMPONENT}" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS + AND NOT "LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${_${_PYTHON_PREFIX}_ID}_ARTIFACTS) + set (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED FALSE) + endif() + endforeach() + if (_${_PYTHON_PREFIX}_LIBRARY_REQUIRED AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) # Don't search for include dir if no library was founded break() @@ -2939,7 +2981,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") if (_${_PYTHON_PREFIX}_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") - set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") + set_property (CACHE _${_PYTHON_PREFIX}_Development_REASON_FAILURE PROPERTY VALUE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() @@ -3033,7 +3075,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Development.Embed_FOUND) OR (NOT "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Development.Module_FOUND)) - unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE) + unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE CACHE) endif() if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS @@ -3144,7 +3186,7 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte set (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") if(_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") - set (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}\"") + set_property (CACHE _${_PYTHON_PREFIX}_NumPy_REASON_FAILURE PROPERTY VALUE "Cannot find the directory \"${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR-NOTFOUND") endif() @@ -3166,7 +3208,7 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte endif() if (${_PYTHON_PREFIX}_NumPy_FOUND) - unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE) + unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE CACHE) # compute and save numpy signature string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE}:${${_PYTHON_PREFIX}_NumPyINCLUDE_DIR}") @@ -3196,7 +3238,7 @@ unset (_${_PYTHON_PREFIX}_REASON_FAILURE) foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Interpreter Compiler Development NumPy) if (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE) string (APPEND _${_PYTHON_PREFIX}_REASON_FAILURE "\n ${_${_PYTHON_PREFIX}_COMPONENT}: ${_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE}") - unset (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE) + unset (_${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_REASON_FAILURE CACHE) endif() endforeach() diff --git a/Modules/FindRuby.cmake b/Modules/FindRuby.cmake index a80758d..b14349f 100644 --- a/Modules/FindRuby.cmake +++ b/Modules/FindRuby.cmake @@ -369,56 +369,17 @@ if(Ruby_EXECUTABLE AND NOT Ruby_VERSION_MAJOR) set(Ruby_VERSION_MAJOR 1) set(Ruby_VERSION_MINOR 9) endif() - # check whether we found 2.0.x - if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?0") + # check whether we found 2.[0-7].x + if(${Ruby_EXECUTABLE} MATCHES "ruby2") set(Ruby_VERSION_MAJOR 2) - set(Ruby_VERSION_MINOR 0) + string(REGEX_REPLACE ${Ruby_EXECUTABLE} "ruby2\\.?([0-7])" "\\1" Ruby_VERSION_MINOR) endif() - # check whether we found 2.1.x - if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?1") - set(Ruby_VERSION_MAJOR 2) - set(Ruby_VERSION_MINOR 1) - endif() - # check whether we found 2.2.x - if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?2") - set(Ruby_VERSION_MAJOR 2) - set(Ruby_VERSION_MINOR 2) - endif() - # check whether we found 2.3.x - if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?3") - set(Ruby_VERSION_MAJOR 2) - set(Ruby_VERSION_MINOR 3) - endif() - # check whether we found 2.4.x - if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?4") - set(Ruby_VERSION_MAJOR 2) - set(Ruby_VERSION_MINOR 4) - endif() - # check whether we found 2.5.x - if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?5") - set(Ruby_VERSION_MAJOR 2) - set(Ruby_VERSION_MINOR 5) - endif() - # check whether we found 2.6.x - if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?6") - set(Ruby_VERSION_MAJOR 2) - set(Ruby_VERSION_MINOR 6) - endif() - # check whether we found 2.7.x - if(${Ruby_EXECUTABLE} MATCHES "ruby2\\.?7") - set(Ruby_VERSION_MAJOR 2) - set(Ruby_VERSION_MINOR 7) - endif() - # check whether we found 3.0.x - if(${Ruby_EXECUTABLE} MATCHES "ruby3\\.?0") - set(Ruby_VERSION_MAJOR 3) - set(Ruby_VERSION_MINOR 0) - endif() - # check whether we found 3.1.x - if(${Ruby_EXECUTABLE} MATCHES "ruby3\\.?1") + # check whether we found 3.[0-1].x + if(${Ruby_EXECUTABLE} MATCHES "ruby3") set(Ruby_VERSION_MAJOR 3) - set(Ruby_VERSION_MINOR 1) + string(REGEX_REPLACE ${Ruby_EXECUTABLE} "ruby3\\.?([0-1])" "\\1" Ruby_VERSION_MINOR) endif() + endif() if(Ruby_VERSION_MAJOR) diff --git a/Modules/FindSDL_gfx.cmake b/Modules/FindSDL_gfx.cmake new file mode 100644 index 0000000..2dd96e9 --- /dev/null +++ b/Modules/FindSDL_gfx.cmake @@ -0,0 +1,86 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindSDL_gfx +----------- + +.. versionadded:: 3.25 + +Locate SDL_gfx library + +This module defines: + +:: + + SDL::SDL_gfx, the name of the target to use with target_*() commands + SDL_GFX_LIBRARIES, the name of the library to link against + SDL_GFX_INCLUDE_DIRS, where to find the headers + SDL_GFX_FOUND, if false, do not try to link against + SDL_GFX_VERSION_STRING - human-readable string containing the + version of SDL_gfx + +``$SDLDIR`` is an environment variable that would correspond to the +``./configure --prefix=$SDLDIR`` used in building SDL. +#]=======================================================================] + +find_path(SDL_GFX_INCLUDE_DIRS + NAMES + SDL_framerate.h + SDL_gfxBlitFunc.h + SDL_gfxPrimitives.h + SDL_gfxPrimitives_font.h + SDL_imageFilter.h + SDL_rotozoom.h + HINTS + ENV SDLGFXDIR + ENV SDLDIR + PATH_SUFFIXES SDL + # path suffixes to search inside ENV{SDLDIR} + include/SDL include/SDL12 include/SDL11 include +) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(VC_LIB_PATH_SUFFIX lib/x64) +else() + set(VC_LIB_PATH_SUFFIX lib/x86) +endif() + +find_library(SDL_GFX_LIBRARIES + NAMES SDL_gfx + HINTS + ENV SDLGFXDIR + ENV SDLDIR + PATH_SUFFIXES lib ${VC_LIB_PATH_SUFFIX} +) + +if(SDL_GFX_INCLUDE_DIRS AND EXISTS "${SDL_GFX_INCLUDE_DIRS}/SDL_gfxPrimitives.h") + file(STRINGS "${SDL_GFX_INCLUDE_DIRS}/SDL_gfxPrimitives.h" SDL_GFX_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_GFXPRIMITIVES_MAJOR[ \t]+[0-9]+$") + file(STRINGS "${SDL_GFX_INCLUDE_DIRS}/SDL_gfxPrimitives.h" SDL_GFX_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_GFXPRIMITIVES_MINOR[ \t]+[0-9]+$") + file(STRINGS "${SDL_GFX_INCLUDE_DIRS}/SDL_gfxPrimitives.h" SDL_GFX_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_GFXPRIMITIVES_MICRO[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SDL_GFXPRIMITIVES_MAJOR[ \t]+([0-9]+)$" "\\1" SDL_GFX_VERSION_MAJOR "${SDL_GFX_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_GFXPRIMITIVES_MINOR[ \t]+([0-9]+)$" "\\1" SDL_GFX_VERSION_MINOR "${SDL_GFX_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SDL_GFXPRIMITIVES_MICRO[ \t]+([0-9]+)$" "\\1" SDL_GFX_VERSION_PATCH "${SDL_GFX_VERSION_PATCH_LINE}") + set(SDL_GFX_VERSION_STRING ${SDL_GFX_VERSION_MAJOR}.${SDL_GFX_VERSION_MINOR}.${SDL_GFX_VERSION_PATCH}) + unset(SDL_GFX_VERSION_MAJOR_LINE) + unset(SDL_GFX_VERSION_MINOR_LINE) + unset(SDL_GFX_VERSION_PATCH_LINE) + unset(SDL_GFX_VERSION_MAJOR) + unset(SDL_GFX_VERSION_MINOR) + unset(SDL_GFX_VERSION_PATCH) +endif() + +include(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL_gfx + REQUIRED_VARS SDL_GFX_LIBRARIES SDL_GFX_INCLUDE_DIRS + VERSION_VAR SDL_GFX_VERSION_STRING) + +if(SDL_gfx_FOUND) + if(NOT TARGET SDL::SDL_gfx) + add_library(SDL::SDL_gfx INTERFACE IMPORTED) + set_target_properties(SDL::SDL_gfx PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${SDL_GFX_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${SDL_GFX_LIBRARIES}") + endif() +endif() diff --git a/Modules/FindSDL_image.cmake b/Modules/FindSDL_image.cmake index e687b49..324fef5 100644 --- a/Modules/FindSDL_image.cmake +++ b/Modules/FindSDL_image.cmake @@ -31,10 +31,6 @@ For backward compatibility the following variables are also set: $SDLDIR is an environment variable that would correspond to the ./configure --prefix=$SDLDIR used in building SDL. - -Created by Eric Wing. This was influenced by the FindSDL.cmake -module, but with modifications to recognize OS X frameworks and -additional Unix paths (FreeBSD, etc). #]=======================================================================] if(NOT SDL_IMAGE_INCLUDE_DIR AND SDLIMAGE_INCLUDE_DIR) diff --git a/Modules/FindSDL_mixer.cmake b/Modules/FindSDL_mixer.cmake index 315400a..8ed3cb4 100644 --- a/Modules/FindSDL_mixer.cmake +++ b/Modules/FindSDL_mixer.cmake @@ -31,10 +31,6 @@ For backward compatibility the following variables are also set: $SDLDIR is an environment variable that would correspond to the ./configure --prefix=$SDLDIR used in building SDL. - -Created by Eric Wing. This was influenced by the FindSDL.cmake -module, but with modifications to recognize OS X frameworks and -additional Unix paths (FreeBSD, etc). #]=======================================================================] if(NOT SDL_MIXER_INCLUDE_DIR AND SDLMIXER_INCLUDE_DIR) diff --git a/Modules/FindSDL_net.cmake b/Modules/FindSDL_net.cmake index 28cb4d6..639e5bd 100644 --- a/Modules/FindSDL_net.cmake +++ b/Modules/FindSDL_net.cmake @@ -30,10 +30,6 @@ For backward compatibility the following variables are also set: $SDLDIR is an environment variable that would correspond to the ./configure --prefix=$SDLDIR used in building SDL. - -Created by Eric Wing. This was influenced by the FindSDL.cmake -module, but with modifications to recognize OS X frameworks and -additional Unix paths (FreeBSD, etc). #]=======================================================================] if(NOT SDL_NET_INCLUDE_DIR AND SDLNET_INCLUDE_DIR) diff --git a/Modules/FindSDL_sound.cmake b/Modules/FindSDL_sound.cmake index 8d2f9f8..d863e3c 100644 --- a/Modules/FindSDL_sound.cmake +++ b/Modules/FindSDL_sound.cmake @@ -54,7 +54,19 @@ Typically, you should not use these variables directly, and you should use SDL_SOUND_LIBRARIES which contains SDL_SOUND_LIBRARY and the other audio libraries (if needed) to successfully compile on your system. -Created by Eric Wing. This module is a bit more complicated than the +Responds to the $SDLDIR and $SDLSOUNDDIR environmental variable that +would correspond to the ./configure --prefix=$SDLDIR used in building +SDL. + +On OSX, this will prefer the Framework version (if found) over others. +People will have to manually change the cache values of SDL_LIBRARY to +override this selectionor set the CMake environment CMAKE_INCLUDE_PATH +to modify the search paths. +#]=======================================================================] + + +#[[ +This module is a bit more complicated than the other FindSDL* family modules. The reason is that SDL_sound can be compiled in a large variety of different ways which are independent of platform. SDL_sound may dynamically link against other 3rd party @@ -70,16 +82,7 @@ This module uses a brute force approach to create a test program that uses SDL_sound, and then tries to build it. If the build fails, it parses the error output for known symbol names to figure out which libraries are needed. - -Responds to the $SDLDIR and $SDLSOUNDDIR environmental variable that -would correspond to the ./configure --prefix=$SDLDIR used in building -SDL. - -On OSX, this will prefer the Framework version (if found) over others. -People will have to manually change the cache values of SDL_LIBRARY to -override this selectionor set the CMake environment CMAKE_INCLUDE_PATH -to modify the search paths. -#]=======================================================================] +#]] set(SDL_SOUND_EXTRAS "" CACHE STRING "SDL_sound extra flags") mark_as_advanced(SDL_SOUND_EXTRAS) @@ -182,9 +185,9 @@ if(SDL_FOUND AND SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) try_compile( MY_RESULT - ${PROJECT_BINARY_DIR}/CMakeTmp - ${PROJECT_BINARY_DIR}/CMakeTmp - DetermineSoundLibs + PROJECT DetermineSoundLibs + SOURCE_DIR ${PROJECT_BINARY_DIR}/CMakeTmp + BINARY_DIR ${PROJECT_BINARY_DIR}/CMakeTmp OUTPUT_VARIABLE MY_OUTPUT ) diff --git a/Modules/FindSDL_ttf.cmake b/Modules/FindSDL_ttf.cmake index d5721da..d67c089 100644 --- a/Modules/FindSDL_ttf.cmake +++ b/Modules/FindSDL_ttf.cmake @@ -30,10 +30,6 @@ For backward compatibility the following variables are also set: $SDLDIR is an environment variable that would correspond to the ./configure --prefix=$SDLDIR used in building SDL. - -Created by Eric Wing. This was influenced by the FindSDL.cmake -module, but with modifications to recognize OS X frameworks and -additional Unix paths (FreeBSD, etc). #]=======================================================================] if(NOT SDL_TTF_INCLUDE_DIR AND SDLTTF_INCLUDE_DIR) diff --git a/Modules/FindThreads.cmake b/Modules/FindThreads.cmake index a675fd6..7326ef9 100644 --- a/Modules/FindThreads.cmake +++ b/Modules/FindThreads.cmake @@ -129,14 +129,12 @@ macro(_threads_check_flag_pthread) elseif(NOT DEFINED THREADS_HAVE_PTHREAD_ARG) message(CHECK_START "Check if compiler accepts -pthread") if(CMAKE_C_COMPILER_LOADED) - set(_threads_src ${CMAKE_CURRENT_LIST_DIR}/CheckForPthreads.c) + set(_threads_src CheckForPthreads.c) elseif(CMAKE_CXX_COMPILER_LOADED) - set(_threads_src ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindThreads/CheckForPthreads.cxx) - configure_file(${CMAKE_CURRENT_LIST_DIR}/CheckForPthreads.c "${_threads_src}" COPYONLY) + set(_threads_src CheckForPthreads.cxx) endif() try_compile(THREADS_HAVE_PTHREAD_ARG - ${CMAKE_BINARY_DIR} - ${_threads_src} + SOURCE_FROM_FILE "${_threads_src}" "${CMAKE_CURRENT_LIST_DIR}/CheckForPthreads.c" CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread OUTPUT_VARIABLE _cmake_check_pthreads_output) diff --git a/Modules/FindVulkan.cmake b/Modules/FindVulkan.cmake index 7ca7d03..3817987 100644 --- a/Modules/FindVulkan.cmake +++ b/Modules/FindVulkan.cmake @@ -36,6 +36,11 @@ There are corresponding imported targets for each of these. ``MoltenVK`` On macOS, an additional component ``MoltenVK`` is available. +``dxc`` + .. versionadded:: 3.25 + + The DirectX Shader Compiler. + The ``glslc`` and ``glslangValidator`` components are provided even if not explicitly requested (for backward compatibility). @@ -89,6 +94,21 @@ This module defines :prop_tgt:`IMPORTED` targets if Vulkan has been found: Defined if SDK has the Khronos library which implement a subset of Vulkan API over Apple Metal graphics framework. (MoltenVK). +``Vulkan::volk`` + .. versionadded:: 3.25 + + Defined if SDK has the Vulkan meta-loader (volk). + +``Vulkan::dxc_lib`` + .. versionadded:: 3.25 + + Defined if SDK has the DirectX shader compiler library. + +``Vulkan::dxc_exe`` + .. versionadded:: 3.25 + + Defined if SDK has the DirectX shader compiler CLI tool. + Result Variables ^^^^^^^^^^^^^^^^ @@ -128,6 +148,21 @@ This module defines the following variables: .. versionadded:: 3.24 True, if the SDK has the MoltenVK library. +``Vulkan_volk_FOUND`` + .. versionadded:: 3.25 + + True, if the SDK has the volk library. + +``Vulkan_dxc_lib_FOUND`` + .. versionadded:: 3.25 + + True, if the SDK has the DirectX shader compiler library. + +``Vulkan_dxc_exe_FOUND`` + .. versionadded:: 3.25 + + True, if the SDK has the DirectX shader compiler CLI tool. + The module will also defines these cache variables: @@ -156,6 +191,21 @@ The module will also defines these cache variables: Path to the MoltenVK library. +``Vulkan_volk_LIBRARY`` + .. versionadded:: 3.25 + + Path to the volk library. + +``Vulkan_dxc_LIBRARY`` + .. versionadded:: 3.25 + + Path to the DirectX shader compiler library. + +``Vulkan_dxc_EXECUTABLE`` + .. versionadded:: 3.25 + + Path to the DirectX shader compiler CLI tool. + Hints ^^^^^ @@ -403,6 +453,27 @@ if(MoltenVK IN_LIST Vulkan_FIND_COMPONENTS) ) mark_as_advanced(Vulkan_MoltenVK_INCLUDE_DIR) endif() +if(volk IN_LIST Vulkan_FIND_COMPONENTS) + find_library(Vulkan_volk_LIBRARY + NAMES volk + HINTS + ${_Vulkan_hint_library_search_paths}) + mark_as_advanced(Vulkan_Volk_LIBRARY) +endif() + +if (dxc IN_LIST Vulkan_FIND_COMPONENTS) + find_library(Vulkan_dxc_LIBRARY + NAMES dxcompiler + HINTS + ${_Vulkan_hint_library_search_paths}) + mark_as_advanced(Vulkan_dxc_LIBRARY) + + find_program(Vulkan_dxc_EXECUTABLE + NAMES dxc + HINTS + ${_Vulkan_hint_executable_search_paths}) + mark_as_advanced(Vulkan_dxc_EXECUTABLE) +endif() if(Vulkan_GLSLC_EXECUTABLE) set(Vulkan_glslc_FOUND TRUE) @@ -416,6 +487,12 @@ else() set(Vulkan_glslangValidator_FOUND FALSE) endif() +if (Vulkan_dxc_EXECUTABLE) + set(Vulkan_dxc_exe_FOUND TRUE) +else() + set(Vulkan_dxc_exe_FOUND FALSE) +endif() + function(_Vulkan_set_library_component_found component) cmake_parse_arguments(PARSE_ARGV 1 _ARG "NO_WARNING" @@ -466,6 +543,8 @@ _Vulkan_set_library_component_found(glslang glslang-genericcodegen) _Vulkan_set_library_component_found(shaderc_combined) _Vulkan_set_library_component_found(SPIRV-Tools) +_Vulkan_set_library_component_found(volk) +_Vulkan_set_library_component_found(dxc) if(Vulkan_MoltenVK_INCLUDE_DIR AND Vulkan_MoltenVK_LIBRARY) set(Vulkan_MoltenVK_FOUND TRUE) @@ -752,6 +831,44 @@ if(Vulkan_FOUND) IMPORTED_LOCATION_DEBUG "${Vulkan_SPIRV-Tools_DEBUG_LIBRARY}") endif() endif() + + if(Vulkan_volk_LIBRARY AND NOT TARGET Vulkan::volk) + add_library(Vulkan::volk STATIC IMPORTED) + set_property(TARGET Vulkan::volk + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + set_property(TARGET Vulkan::volk APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::volk APPEND + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_volk_LIBRARY}") + + if (NOT WIN32) + set_property(TARGET Vulkan::volk APPEND + PROPERTY + IMPORTED_LINK_INTERFACE_LIBRARIES dl) + endif() + endif() + + if (Vulkan_dxc_LIBRARY AND NOT TARGET Vulkan::dxc_lib) + add_library(Vulkan::dxc_lib STATIC IMPORTED) + set_property(TARGET Vulkan::dxc_lib + PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "${Vulkan_INCLUDE_DIRS}") + set_property(TARGET Vulkan::dxc_lib APPEND + PROPERTY + IMPORTED_CONFIGURATIONS Release) + set_property(TARGET Vulkan::dxc_lib APPEND + PROPERTY + IMPORTED_LOCATION_RELEASE "${Vulkan_dxc_LIBRARY}") + endif() + + if(Vulkan_dxc_EXECUTABLE AND NOT TARGET Vulkan::dxc_exe) + add_executable(Vulkan::dxc_exe IMPORTED) + set_property(TARGET Vulkan::dxc_exe PROPERTY IMPORTED_LOCATION "${Vulkan_dxc_EXECUTABLE}") + endif() + endif() if(Vulkan_MoltenVK_FOUND) diff --git a/Modules/FortranCInterface.cmake b/Modules/FortranCInterface.cmake index 53df01a..af025af 100644 --- a/Modules/FortranCInterface.cmake +++ b/Modules/FortranCInterface.cmake @@ -361,10 +361,10 @@ function(FortranCInterface_VERIFY) # Build a sample project which reports symbols. set(CMAKE_TRY_COMPILE_CONFIGURATION Release) try_compile(FortranCInterface_VERIFY_${lang}_COMPILED - ${FortranCInterface_BINARY_DIR}/Verify${lang} - ${FortranCInterface_SOURCE_DIR}/Verify - VerifyFortranC # project name - VerifyFortranC # target name + PROJECT VerifyFortranC + TARGET VerifyFortranC + SOURCE_DIR ${FortranCInterface_SOURCE_DIR}/Verify + BINARY_DIR ${FortranCInterface_BINARY_DIR}/Verify${lang} CMAKE_FLAGS -DVERIFY_CXX=${verify_cxx} -DCMAKE_VERBOSE_MAKEFILE=ON "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}" diff --git a/Modules/FortranCInterface/Detect.cmake b/Modules/FortranCInterface/Detect.cmake index 567fc37..6401aed 100644 --- a/Modules/FortranCInterface/Detect.cmake +++ b/Modules/FortranCInterface/Detect.cmake @@ -47,10 +47,10 @@ unset(_FortranCInterface_CMP0056) # Build a sample project which reports symbols. set(CMAKE_TRY_COMPILE_CONFIGURATION Release) try_compile(FortranCInterface_COMPILED - ${FortranCInterface_BINARY_DIR} - ${FortranCInterface_SOURCE_DIR} - FortranCInterface # project name - FortranCInterface # target name + PROJECT FortranCInterface + TARGET FortranCInterface + SOURCE_DIR ${FortranCInterface_SOURCE_DIR} + BINARY_DIR ${FortranCInterface_BINARY_DIR} CMAKE_FLAGS "-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}" "-DCMAKE_Fortran_FLAGS:STRING=${CMAKE_Fortran_FLAGS}" diff --git a/Modules/GoogleTest.cmake b/Modules/GoogleTest.cmake index f5f4f02..b8dc482 100644 --- a/Modules/GoogleTest.cmake +++ b/Modules/GoogleTest.cmake @@ -348,7 +348,7 @@ function(gtest_add_tests) unset(testList) set(gtest_case_name_regex ".*\\( *([A-Za-z_0-9]+) *, *([A-Za-z_0-9]+) *\\).*") - set(gtest_test_type_regex "(TYPED_TEST|TEST_?[FP]?)") + set(gtest_test_type_regex "(TYPED_TEST|TEST)_?[FP]?") foreach(source IN LISTS ARGS_SOURCES) if(NOT ARGS_SKIP_DEPENDENCY) @@ -361,7 +361,9 @@ function(gtest_add_tests) # Parameterized tests have a different signature for the filter if("x${test_type}" STREQUAL "xTEST_P") - string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" gtest_test_name ${hit}) + string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" gtest_test_name ${hit}) + elseif("x${test_type}" STREQUAL "xTYPED_TEST_P") + string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1/*.\\2" gtest_test_name ${hit}) elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST") string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" gtest_test_name ${hit}) elseif("x${test_type}" STREQUAL "xTYPED_TEST") diff --git a/Modules/Internal/CPack/CPackDeb.cmake b/Modules/Internal/CPack/CPackDeb.cmake index 958a6db..38e32c2 100644 --- a/Modules/Internal/CPack/CPackDeb.cmake +++ b/Modules/Internal/CPack/CPackDeb.cmake @@ -37,8 +37,8 @@ endfunction() #extract library name and version for given shared object function(extract_so_info shared_object libname version) - if(READELF_EXECUTABLE) - execute_process(COMMAND "${READELF_EXECUTABLE}" -d "${shared_object}" + if(CPACK_READELF_EXECUTABLE) + execute_process(COMMAND "${CPACK_READELF_EXECUTABLE}" -d "${shared_object}" WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" RESULT_VARIABLE result OUTPUT_VARIABLE output @@ -197,15 +197,15 @@ function(cpack_deb_prepare_package_vars) endforeach() endif() - find_program(READELF_EXECUTABLE NAMES readelf) + find_program(CPACK_READELF_EXECUTABLE NAMES readelf) if(CPACK_DEBIAN_DEBUGINFO_PACKAGE AND CPACK_DEB_UNSTRIPPED_FILES) - find_program(OBJCOPY_EXECUTABLE NAMES objcopy) + find_program(CPACK_OBJCOPY_EXECUTABLE NAMES objcopy) - if(NOT OBJCOPY_EXECUTABLE) + if(NOT CPACK_OBJCOPY_EXECUTABLE) message(FATAL_ERROR "debuginfo packages require the objcopy tool") endif() - if(NOT READELF_EXECUTABLE) + if(NOT CPACK_READELF_EXECUTABLE) message(FATAL_ERROR "debuginfo packages require the readelf tool") endif() @@ -213,7 +213,7 @@ function(cpack_deb_prepare_package_vars) foreach(_FILE IN LISTS CPACK_DEB_UNSTRIPPED_FILES) # Get the file's Build ID - execute_process(COMMAND env LC_ALL=C ${READELF_EXECUTABLE} -n "${_FILE}" + execute_process(COMMAND env LC_ALL=C ${CPACK_READELF_EXECUTABLE} -n "${_FILE}" WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" OUTPUT_VARIABLE READELF_OUTPUT RESULT_VARIABLE READELF_RESULT @@ -221,7 +221,7 @@ function(cpack_deb_prepare_package_vars) OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT READELF_RESULT EQUAL 0) message(FATAL_ERROR "CPackDeb: readelf: '${READELF_ERROR}';\n" - "executed command: '${READELF_EXECUTABLE} -n ${_FILE}'") + "executed command: '${CPACK_READELF_EXECUTABLE} -n ${_FILE}'") endif() if(READELF_OUTPUT MATCHES "Build ID: ([0-9a-zA-Z][0-9a-zA-Z])([0-9a-zA-Z]*)") set(_BUILD_ID_START ${CMAKE_MATCH_1}) @@ -235,7 +235,7 @@ function(cpack_deb_prepare_package_vars) set(_FILE_DBGSYM ${_DBGSYM_ROOT}/usr/lib/debug/.build-id/${_BUILD_ID_START}/${_BUILD_ID_REMAINING}.debug) get_filename_component(_OUT_DIR "${_FILE_DBGSYM}" DIRECTORY) file(MAKE_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}/${_OUT_DIR}") - execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --only-keep-debug "${_FILE}" "${_FILE_DBGSYM}" + execute_process(COMMAND ${CPACK_OBJCOPY_EXECUTABLE} --only-keep-debug "${_FILE}" "${_FILE_DBGSYM}" WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" OUTPUT_VARIABLE OBJCOPY_OUTPUT RESULT_VARIABLE OBJCOPY_RESULT @@ -243,9 +243,9 @@ function(cpack_deb_prepare_package_vars) OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT OBJCOPY_RESULT EQUAL 0) message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n" - "executed command: '${OBJCOPY_EXECUTABLE} --only-keep-debug ${_FILE} ${_FILE_DBGSYM}'") + "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --only-keep-debug ${_FILE} ${_FILE_DBGSYM}'") endif() - execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --strip-unneeded ${_FILE} + execute_process(COMMAND ${CPACK_OBJCOPY_EXECUTABLE} --strip-unneeded ${_FILE} WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" OUTPUT_VARIABLE OBJCOPY_OUTPUT RESULT_VARIABLE OBJCOPY_RESULT @@ -253,9 +253,9 @@ function(cpack_deb_prepare_package_vars) OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT OBJCOPY_RESULT EQUAL 0) message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n" - "executed command: '${OBJCOPY_EXECUTABLE} --strip-debug ${_FILE}'") + "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --strip-debug ${_FILE}'") endif() - execute_process(COMMAND ${OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE} + execute_process(COMMAND ${CPACK_OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE} WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" OUTPUT_VARIABLE OBJCOPY_OUTPUT RESULT_VARIABLE OBJCOPY_RESULT @@ -263,7 +263,7 @@ function(cpack_deb_prepare_package_vars) OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT OBJCOPY_RESULT EQUAL 0) message(FATAL_ERROR "CPackDeb: objcopy: '${OBJCOPY_ERROR}';\n" - "executed command: '${OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}'") + "executed command: '${CPACK_OBJCOPY_EXECUTABLE} --add-gnu-debuglink=${_FILE_DBGSYM} ${_FILE}'") endif() endforeach() endif() @@ -652,7 +652,7 @@ function(cpack_deb_prepare_package_vars) unset(CPACK_DEBIAN_PACKAGE_SHLIBS_LIST) if(CPACK_DEBIAN_PACKAGE_GENERATE_SHLIBS) - if(READELF_EXECUTABLE) + if(CPACK_READELF_EXECUTABLE) foreach(_FILE IN LISTS CPACK_DEB_SHARED_OBJECT_FILES) extract_so_info("${_FILE}" libname soversion) if(libname AND DEFINED soversion) diff --git a/Modules/Internal/CPack/CPackRPM.cmake b/Modules/Internal/CPack/CPackRPM.cmake index cd631b8..7c10280 100644 --- a/Modules/Internal/CPack/CPackRPM.cmake +++ b/Modules/Internal/CPack/CPackRPM.cmake @@ -625,8 +625,8 @@ function(cpack_rpm_debugsymbol_check INSTALL_FILES WORKING_DIR) endif() # With objdump we should check the debug symbols - find_program(OBJDUMP_EXECUTABLE objdump) - if(NOT OBJDUMP_EXECUTABLE) + find_program(CPACK_OBJDUMP_EXECUTABLE objdump) + if(NOT CPACK_OBJDUMP_EXECUTABLE) message(FATAL_ERROR "CPackRPM: objdump binary could not be found!" " Required for debuginfo packaging. See documentation of" " CPACK_RPM_DEBUGINFO_PACKAGE variable for details.") @@ -649,7 +649,7 @@ function(cpack_rpm_debugsymbol_check INSTALL_FILES WORKING_DIR) continue() endif() - execute_process(COMMAND "${OBJDUMP_EXECUTABLE}" -h ${WORKING_DIR}/${F} + execute_process(COMMAND "${CPACK_OBJDUMP_EXECUTABLE}" -h ${WORKING_DIR}/${F} WORKING_DIRECTORY "${CPACK_TOPLEVEL_DIRECTORY}" RESULT_VARIABLE OBJDUMP_EXEC_RESULT OUTPUT_VARIABLE OBJDUMP_OUT diff --git a/Modules/Internal/CheckSourceCompiles.cmake b/Modules/Internal/CheckSourceCompiles.cmake index 27aa3e0..eadf3da 100644 --- a/Modules/Internal/CheckSourceCompiles.cmake +++ b/Modules/Internal/CheckSourceCompiles.cmake @@ -86,15 +86,13 @@ function(CMAKE_CHECK_SOURCE_COMPILES _lang _source _var) else() set(CHECK_${LANG}_SOURCE_COMPILES_ADD_INCLUDES) endif() - file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT}" - "${_source}\n") if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_START "Performing Test ${_var}") endif() + string(APPEND _source "\n") try_compile(${_var} - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT} + SOURCE_FROM_VAR "src.${_SRC_EXT}" _source COMPILE_DEFINITIONS -D${_var} ${CMAKE_REQUIRED_DEFINITIONS} ${CHECK_${LANG}_SOURCE_COMPILES_ADD_LINK_OPTIONS} ${CHECK_${LANG}_SOURCE_COMPILES_ADD_LIBRARIES} diff --git a/Modules/Internal/CheckSourceRuns.cmake b/Modules/Internal/CheckSourceRuns.cmake index 75e9896..09c85c5 100644 --- a/Modules/Internal/CheckSourceRuns.cmake +++ b/Modules/Internal/CheckSourceRuns.cmake @@ -85,15 +85,13 @@ function(CMAKE_CHECK_SOURCE_RUNS _lang _source _var) else() set(CHECK_${_lang}_SOURCE_COMPILES_ADD_INCLUDES) endif() - file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT}" - "${_source}\n") if(NOT CMAKE_REQUIRED_QUIET) message(CHECK_START "Performing Test ${_var}") endif() + string(APPEND _source "\n") try_run(${_var}_EXITCODE ${_var}_COMPILED - ${CMAKE_BINARY_DIR} - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.${_SRC_EXT} + SOURCE_FROM_VAR "src.${_SRC_EXT}" _source COMPILE_DEFINITIONS -D${_var} ${CMAKE_REQUIRED_DEFINITIONS} ${CHECK_${_lang}_SOURCE_COMPILES_ADD_LINK_OPTIONS} ${CHECK_${_lang}_SOURCE_COMPILES_ADD_LIBRARIES} diff --git a/Modules/Internal/FeatureTesting.cmake b/Modules/Internal/FeatureTesting.cmake index b6f3c09..5c144ec 100644 --- a/Modules/Internal/FeatureTesting.cmake +++ b/Modules/Internal/FeatureTesting.cmake @@ -4,7 +4,7 @@ macro(_record_compiler_features lang compile_flags feature_list) string(TOLOWER ${lang} lang_lc) file(REMOVE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin") - file(WRITE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" " + set(_content " const char features[] = {\"\\n\"\n") get_property(known_features GLOBAL PROPERTY CMAKE_${lang}_KNOWN_FEATURES) @@ -16,10 +16,11 @@ macro(_record_compiler_features lang compile_flags feature_list) else() set(_feature_condition "#if ${_cmake_feature_test_${feature}}\n\"1\"\n#else\n\"0\"\n#endif\n") endif() - file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" "\"${lang}_FEATURE:\"\n${_feature_condition}\"${feature}\\n\"\n") + string(APPEND _content + "\"${lang}_FEATURE:\"\n${_feature_condition}\"${feature}\\n\"\n") endif() endforeach() - file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" + string(APPEND _content "\n};\n\nint main(int argc, char** argv) { (void)argv; return features[argc]; }\n") if(CMAKE_${lang}_LINK_WITH_STANDARD_COMPILE_OPTION) @@ -31,7 +32,7 @@ macro(_record_compiler_features lang compile_flags feature_list) endif() try_compile(CMAKE_${lang}_FEATURE_TEST - ${CMAKE_BINARY_DIR} "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" + SOURCE_FROM_VAR "feature_tests.${lang_lc}" _content COMPILE_DEFINITIONS "${compile_flags}" LINK_LIBRARIES "${compile_flags_for_link}" OUTPUT_VARIABLE _output diff --git a/Modules/Platform/AIX-GNU.cmake b/Modules/Platform/AIX-GNU.cmake index 5a532c7..a9aa8e0 100644 --- a/Modules/Platform/AIX-GNU.cmake +++ b/Modules/Platform/AIX-GNU.cmake @@ -23,11 +23,11 @@ macro(__aix_compiler_gnu lang) # Construct the export list ourselves to pass only the object files so # that we export only the symbols actually provided by the sources. set(CMAKE_${lang}_CREATE_SHARED_LIBRARY - "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS> <OBJECTS>" + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp -c <CMAKE_${lang}_COMPILER> <AIX_EXPORTS> <OBJECTS>" "<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" ) set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS - "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>" + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>" "<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") endmacro() diff --git a/Modules/Platform/AIX-XL.cmake b/Modules/Platform/AIX-XL.cmake index 2a8c159..902cbb3 100644 --- a/Modules/Platform/AIX-XL.cmake +++ b/Modules/Platform/AIX-XL.cmake @@ -29,12 +29,12 @@ macro(__aix_compiler_xl lang) # Construct the export list ourselves to pass only the object files so # that we export only the symbols actually provided by the sources. set(CMAKE_${lang}_CREATE_SHARED_LIBRARY - "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp <AIX_EXPORTS>${_OBJECTS}" + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <OBJECT_DIR>/exports.exp -c <CMAKE_${lang}_COMPILER> <AIX_EXPORTS>${_OBJECTS}" "<CMAKE_${lang}_COMPILER> <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> -Wl,-bE:<OBJECT_DIR>/exports.exp <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" ) set(CMAKE_${lang}_LINK_EXECUTABLE_WITH_EXPORTS - "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -l . <AIX_EXPORTS> <OBJECTS>" + "\"${CMAKE_ROOT}/Modules/Platform/AIX/ExportImportList\" -o <TARGET_IMPLIB> -c <CMAKE_${lang}_COMPILER> -l . <AIX_EXPORTS> <OBJECTS>" "<CMAKE_${lang}_COMPILER> <FLAGS> <CMAKE_${lang}_LINK_FLAGS> -Wl,-bE:<TARGET_IMPLIB> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>") unset(_OBJECTS) diff --git a/Modules/Platform/AIX/ExportImportList b/Modules/Platform/AIX/ExportImportList index 891bce7..5e16fcb 100755 --- a/Modules/Platform/AIX/ExportImportList +++ b/Modules/Platform/AIX/ExportImportList @@ -5,7 +5,7 @@ # This script is internal to CMake and meant only to be # invoked by CMake-generated build systems on AIX. -usage='usage: ExportImportList -o <out-file> [-l <lib>] [-n] [--] <objects>...' +usage='usage: ExportImportList -o <out-file> -c <compiler> [-l <lib>] [-n] [--] <objects>...' die() { echo "$@" 1>&2; exit 1 @@ -15,11 +15,13 @@ die() { out='' lib='' no_objects='' +compiler='' while test "$#" != 0; do case "$1" in -l) shift; lib="$1" ;; -o) shift; out="$1" ;; -n) no_objects='1' ;; + -c) shift; compiler="$1" ;; --) shift; break ;; -*) die "$usage" ;; *) break ;; @@ -27,27 +29,47 @@ while test "$#" != 0; do shift done test -n "$out" || die "$usage" +# We need the compiler executable to resolve where the ibm-llvm-nm executable is +test -n "$compiler" || die "$usage" # Build a temporary file that atomically replaces the output later. out_tmp="$out.tmp$$" trap 'rm -f "$out_tmp"' EXIT INT TERM > "$out_tmp" +# If IPA was enabled and a compiler from the IBMClang family is used, then +# the object files contain LLVM bitcode[0] rather than XCOFF objects and so +# need to be handled differently. +# +# [0]: https://www.ibm.com/docs/en/openxl-c-and-cpp-aix/17.1.0?topic=compatibility-link-time-optimization-lto +NM="$(dirname "$compiler")/../libexec/ibm-llvm-nm" + +function IsBitcode { + # N4 = first 4 bytes, -tx = output in hexadecimal, -An = don't display offset + # cut: trim off the preceding whitespace where the offset would be + # 4243code is the hexadecimal magic number for LLVM bitcode + [ "$(od -N4 -tx -An $1 | cut -d ' ' -f 2)" == "4243c0de" ]; +} + # Collect symbols exported from all object files. if test -z "$no_objects"; then for f in "$@"; do - dump -tov -X 32_64 "$f" | - awk ' - BEGIN { - V["EXPORTED"]=" export" - V["PROTECTED"]=" protected" - } - /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / { - if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) { - print $NF V[$(NF-1)] + if IsBitcode "$f"; then + "$NM" "$f" --defined-only --extern-only --just-symbol-name 2>/dev/null + else + dump -tov -X 32_64 "$f" | + awk ' + BEGIN { + V["EXPORTED"]=" export" + V["PROTECTED"]=" protected" + } + /^\[[0-9]+\]\tm +[^ ]+ +\.(text|data|bss) +[^ ]+ +(extern|weak) +(EXPORTED|PROTECTED| ) / { + if (!match($NF,/^(\.|__sinit|__sterm|__[0-9]+__)/)) { + print $NF V[$(NF-1)] + } } - } - ' + ' + fi done >> "$out_tmp" fi diff --git a/Modules/Platform/DragonFly.cmake b/Modules/Platform/DragonFly.cmake index 12e5f3c..994ba79 100644 --- a/Modules/Platform/DragonFly.cmake +++ b/Modules/Platform/DragonFly.cmake @@ -3,6 +3,7 @@ # see http://archive.netbsd.se/?ml=dfbsd-users&a=2007-07&m=4678361 include(Platform/FreeBSD) +set(BSD "DragonFlyBSD") # DragonFly BSD requires -z origin to enable $ORIGIN expansion in RPATH. # This is not required for FreeBSD since 10.2-RELEASE. diff --git a/Modules/Platform/FreeBSD.cmake b/Modules/Platform/FreeBSD.cmake index bd5a786..9cd9399 100644 --- a/Modules/Platform/FreeBSD.cmake +++ b/Modules/Platform/FreeBSD.cmake @@ -1,3 +1,4 @@ +set(BSD "FreeBSD") set(CMAKE_DL_LIBS "") set(CMAKE_C_COMPILE_OPTIONS_PIC "-fPIC") set(CMAKE_C_COMPILE_OPTIONS_PIE "-fPIE") diff --git a/Modules/Platform/Linux-IntelLLVM.cmake b/Modules/Platform/Linux-IntelLLVM.cmake index 1363b44..992f80e 100644 --- a/Modules/Platform/Linux-IntelLLVM.cmake +++ b/Modules/Platform/Linux-IntelLLVM.cmake @@ -8,18 +8,6 @@ if(__LINUX_COMPILER_INTEL_LLVM) endif() set(__LINUX_COMPILER_INTEL_LLVM 1) -if(NOT XIAR) - set(_intel_xiar_hints) - foreach(lang C CXX Fortran) - if(IS_ABSOLUTE "${CMAKE_${lang}_COMPILER}") - get_filename_component(_hint "${CMAKE_${lang}_COMPILER}" PATH) - list(APPEND _intel_xiar_hints ${_hint}) - endif() - endforeach() - find_program(XIAR NAMES xiar HINTS ${_intel_xiar_hints}) - mark_as_advanced(XIAR) -endif() - macro(__linux_compiler_intel_llvm lang) set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") @@ -37,19 +25,5 @@ macro(__linux_compiler_intel_llvm lang) set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "-Wl,") set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP ",") - set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES) - - if(XIAR) - # INTERPROCEDURAL_OPTIMIZATION - set(CMAKE_${lang}_COMPILE_OPTIONS_IPO -ipo) - set(CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO - "${XIAR} cr <TARGET> <LINK_FLAGS> <OBJECTS> " - "${XIAR} -s <TARGET> ") - set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) - set(_CMAKE_${lang}_IPO_LEGACY_BEHAVIOR YES) - else() - set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) - endif() - set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=") endmacro() diff --git a/Modules/Platform/Linux-NVHPC.cmake b/Modules/Platform/Linux-NVHPC.cmake index aad17f1..602b417 100644 --- a/Modules/Platform/Linux-NVHPC.cmake +++ b/Modules/Platform/Linux-NVHPC.cmake @@ -3,13 +3,15 @@ # This module is shared by multiple languages; use include blocker. -if(__LINUX_COMPILER_NVIDIA) - return() -endif() -set(__LINUX_COMPILER_NVIDIA 1) - -include(Platform/Linux-PGI) +include_guard() macro(__linux_compiler_nvhpc lang) - __linux_compiler_pgi(${lang}) + set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC") + set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE") + set(_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER YES) + set(CMAKE_${lang}_LINK_OPTIONS_PIE "-fPIE") + set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "") + set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC") + set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared") + set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "") endmacro() diff --git a/Modules/Platform/Linux.cmake b/Modules/Platform/Linux.cmake index a7e58ab..e3d444e 100644 --- a/Modules/Platform/Linux.cmake +++ b/Modules/Platform/Linux.cmake @@ -1,3 +1,4 @@ +set(LINUX 1) set(CMAKE_DL_LIBS "dl") set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,") set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP ":") diff --git a/Modules/Platform/NetBSD.cmake b/Modules/Platform/NetBSD.cmake index ab85923..52c6594 100644 --- a/Modules/Platform/NetBSD.cmake +++ b/Modules/Platform/NetBSD.cmake @@ -1,3 +1,4 @@ +set(BSD "NetBSD") set(CMAKE_DL_LIBS "") set(CMAKE_C_COMPILE_OPTIONS_PIC "-fPIC") set(CMAKE_C_COMPILE_OPTIONS_PIE "-fPIE") diff --git a/Modules/Platform/OpenBSD.cmake b/Modules/Platform/OpenBSD.cmake index 97e2a6a..51ea60d 100644 --- a/Modules/Platform/OpenBSD.cmake +++ b/Modules/Platform/OpenBSD.cmake @@ -1,4 +1,5 @@ include(Platform/NetBSD) +set(BSD "OpenBSD") # On OpenBSD, the compile time linker does not share it's configuration with # the runtime linker. This will extract the library search paths from the diff --git a/Modules/Platform/SerenityOS-Clang-ASM.cmake b/Modules/Platform/SerenityOS-Clang-ASM.cmake new file mode 100644 index 0000000..ba1e18c --- /dev/null +++ b/Modules/Platform/SerenityOS-Clang-ASM.cmake @@ -0,0 +1,2 @@ +include(Platform/SerenityOS-GNU) +__serenity_compiler_gnu(ASM) diff --git a/Modules/Platform/SerenityOS-Clang-C.cmake b/Modules/Platform/SerenityOS-Clang-C.cmake new file mode 100644 index 0000000..791a197 --- /dev/null +++ b/Modules/Platform/SerenityOS-Clang-C.cmake @@ -0,0 +1,2 @@ +include(Platform/SerenityOS-GNU) +__serenity_compiler_gnu(C) diff --git a/Modules/Platform/SerenityOS-Clang-CXX.cmake b/Modules/Platform/SerenityOS-Clang-CXX.cmake new file mode 100644 index 0000000..084e319 --- /dev/null +++ b/Modules/Platform/SerenityOS-Clang-CXX.cmake @@ -0,0 +1,2 @@ +include(Platform/SerenityOS-GNU) +__serenity_compiler_gnu(CXX) diff --git a/Modules/Platform/SerenityOS-GNU-ASM.cmake b/Modules/Platform/SerenityOS-GNU-ASM.cmake new file mode 100644 index 0000000..ba1e18c --- /dev/null +++ b/Modules/Platform/SerenityOS-GNU-ASM.cmake @@ -0,0 +1,2 @@ +include(Platform/SerenityOS-GNU) +__serenity_compiler_gnu(ASM) diff --git a/Modules/Platform/SerenityOS-GNU-C.cmake b/Modules/Platform/SerenityOS-GNU-C.cmake new file mode 100644 index 0000000..791a197 --- /dev/null +++ b/Modules/Platform/SerenityOS-GNU-C.cmake @@ -0,0 +1,2 @@ +include(Platform/SerenityOS-GNU) +__serenity_compiler_gnu(C) diff --git a/Modules/Platform/SerenityOS-GNU-CXX.cmake b/Modules/Platform/SerenityOS-GNU-CXX.cmake new file mode 100644 index 0000000..084e319 --- /dev/null +++ b/Modules/Platform/SerenityOS-GNU-CXX.cmake @@ -0,0 +1,2 @@ +include(Platform/SerenityOS-GNU) +__serenity_compiler_gnu(CXX) diff --git a/Modules/Platform/SerenityOS-GNU.cmake b/Modules/Platform/SerenityOS-GNU.cmake new file mode 100644 index 0000000..ed39477 --- /dev/null +++ b/Modules/Platform/SerenityOS-GNU.cmake @@ -0,0 +1,24 @@ +# This module is shared by multiple languages; use include blocker. +include_guard() + +set(CMAKE_EXE_LINKER_FLAGS_INIT "-Wl,--hash-style=gnu,-z,relro,-z,now,-z,noexecstack,-z,separate-code,-z,max-page-size=0x1000") + +macro(__serenity_compiler_gnu lang) + set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG "-Wl,-rpath,") + set(CMAKE_SHARED_LIBRARY_RUNTIME_${lang}_FLAG_SEP ":") + set(CMAKE_SHARED_LIBRARY_RPATH_LINK_${lang}_FLAG "-Wl,-rpath-link,") + set(CMAKE_SHARED_LIBRARY_SONAME_${lang}_FLAG "-Wl,-soname,") + set(CMAKE_EXE_EXPORTS_${lang}_FLAG "-Wl,--export-dynamic") + + set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared -Wl,--hash-style=gnu,-z,relro,-z,now,-z,noexecstack,-z,separate-code") + + # Initialize link type selection flags. These flags are used when + # building a shared library, shared module, or executable that links + # to other libraries to select whether to use the static or shared + # versions of the libraries. + foreach(type SHARED_LIBRARY SHARED_MODULE EXE) + set(CMAKE_${type}_LINK_STATIC_${lang}_FLAGS "-Wl,-Bstatic") + set(CMAKE_${type}_LINK_DYNAMIC_${lang}_FLAGS "-Wl,-Bdynamic") + endforeach() + +endmacro() diff --git a/Modules/Platform/SerenityOS.cmake b/Modules/Platform/SerenityOS.cmake new file mode 100644 index 0000000..dc4f369 --- /dev/null +++ b/Modules/Platform/SerenityOS.cmake @@ -0,0 +1,12 @@ + +set(SERENITYOS 1) + +set(CMAKE_DL_LIBS "") +set(CMAKE_SHARED_LIBRARY_RPATH_ORIGIN_TOKEN "\$ORIGIN") +set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") + +# Shared libraries with no builtin soname may not be linked safely by +# specifying the file path. +set(CMAKE_PLATFORM_USES_PATH_WHEN_NO_SONAME 1) + +include(Platform/UnixPaths) diff --git a/Modules/Platform/Windows-Clang-HIP.cmake b/Modules/Platform/Windows-Clang-HIP.cmake new file mode 100644 index 0000000..20879fa --- /dev/null +++ b/Modules/Platform/Windows-Clang-HIP.cmake @@ -0,0 +1,19 @@ +include(Platform/Windows-Clang) +set(_COMPILE_HIP_MSVC " -TP") +__windows_compiler_clang(HIP) + +if("x${CMAKE_HIP_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") + if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" + AND CMAKE_DEPFILE_FLAGS_HIP) + set(CMAKE_HIP_DEPENDS_USE_COMPILER TRUE) + endif() +elseif("x${CMAKE_HIP_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU") + if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) + AND CMAKE_GENERATOR MATCHES "Makefiles|WMake" + AND CMAKE_DEPFILE_FLAGS_HIP) + # dependencies are computed by the compiler itself + set(CMAKE_HIP_DEPFILE_FORMAT gcc) + set(CMAKE_HIP_DEPENDS_USE_COMPILER TRUE) + endif() +endif() diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake index 3941311..33d271d 100644 --- a/Modules/Platform/Windows-Clang.cmake +++ b/Modules/Platform/Windows-Clang.cmake @@ -89,17 +89,27 @@ macro(__windows_compiler_clang_gnu lang) set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd) if(CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT) - set(__ADDED_FLAGS "") - set(__ADDED_FLAGS_DEBUG "") + set(_RTL_FLAGS "") + set(_RTL_FLAGS_DEBUG "") else() - set(__ADDED_FLAGS_DEBUG "-D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd") - set(__ADDED_FLAGS "-D_DLL -D_MT -Xclang --dependent-lib=msvcrt") + set(_RTL_FLAGS_DEBUG " -D_DEBUG -D_DLL -D_MT -Xclang --dependent-lib=msvcrtd") + set(_RTL_FLAGS " -D_DLL -D_MT -Xclang --dependent-lib=msvcrt") endif() - string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g -Xclang -gcodeview -O0 ${__ADDED_FLAGS_DEBUG}") - string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG ${__ADDED_FLAGS}") - string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3 -DNDEBUG ${__ADDED_FLAGS}") - string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -g -DNDEBUG -Xclang -gcodeview ${__ADDED_FLAGS}") + if(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT) + set(_DBG_FLAGS "") + else() + set(_DBG_FLAGS " -g -Xclang -gcodeview") + endif() + + string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -O0${_DBG_FLAGS}${_RTL_FLAGS_DEBUG}") + string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Os -DNDEBUG${_RTL_FLAGS}") + string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -O3 -DNDEBUG${_RTL_FLAGS}") + string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -O2 -DNDEBUG${_DBG_FLAGS}${_RTL_FLAGS}") + + set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -g -Xclang -gcodeview) + #set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase) # not supported by Clang + #set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue) # not supported by Clang endif() set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ") set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON) @@ -109,8 +119,9 @@ macro(__windows_compiler_clang_gnu lang) set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Xclang -include-pch -Xclang <PCH_FILE> -Xclang -include -Xclang <PCH_HEADER>) set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Xclang -emit-pch -Xclang -include -Xclang <PCH_HEADER> -x ${__pch_header_${lang}}) - unset(__ADDED_FLAGS) - unset(__ADDED_FLAGS_DEBUG) + unset(_DBG_FLAGS) + unset(_RTL_FLAGS) + unset(_RTL_FLAGS_DEBUG) string(TOLOWER "${CMAKE_BUILD_TYPE}" BUILD_TYPE_LOWER) set(CMAKE_${lang}_STANDARD_LIBRARIES_INIT "-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -loldnames") @@ -146,24 +157,36 @@ macro(__enable_llvm_rc_preprocessing clang_option_prefix extra_pp_flags) endif() endmacro() +macro(__verify_same_language_values variable) + foreach(lang "C" "CXX" "HIP") + if(DEFINED CMAKE_${lang}_${variable}) + list(APPEND __LANGUAGE_VALUES_${variable} "${CMAKE_${lang}_${variable}}") + endif() + endforeach() + list(REMOVE_DUPLICATES __LANGUAGE_VALUES_${variable}) + list(LENGTH __LANGUAGE_VALUES_${variable} __NUM_VALUES) + + if(__NUM_VALUES GREATER 1) + message(FATAL_ERROR ${ARGN}) + endif() + unset(__NUM_VALUES) + unset(__LANGUAGE_VALUES_${variable}) +endmacro() if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" - OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") + OR "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC" + OR "x${CMAKE_HIP_SIMULATE_ID}" STREQUAL "xMSVC") - if ( DEFINED CMAKE_C_COMPILER_ID AND DEFINED CMAKE_CXX_COMPILER_ID - AND NOT "x${CMAKE_C_COMPILER_ID}" STREQUAL "x${CMAKE_CXX_COMPILER_ID}") - message(FATAL_ERROR "The current configuration mixes Clang and MSVC or " - "some other CL compatible compiler tool. This is not supported. " - "Use either clang or MSVC as both C and C++ compilers.") - endif() + __verify_same_language_values(COMPILER_ID + "The current configuration mixes Clang and MSVC or " + "some other CL compatible compiler tool. This is not supported. " + "Use either clang or MSVC as both C, C++ and/or HIP compilers.") - if ( DEFINED CMAKE_C_COMPILER_FRONTEND_VARIANT AND DEFINED CMAKE_CXX_COMPILER_FRONTEND_VARIANT - AND NOT "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}") - message(FATAL_ERROR "The current configuration uses the Clang compiler " - "tool with mixed frontend variants, both the GNU and in MSVC CL " - "like variants. This is not supported. Use either clang/clang++ " - "or clang-cl as both C and C++ compilers.") - endif() + __verify_same_language_values(COMPILER_FRONTEND_VARIANT + "The current configuration uses the Clang compiler " + "tool with mixed frontend variants, both the GNU and in MSVC CL " + "like variants. This is not supported. Use either clang/clang++ " + "or clang-cl as both C, C++ and/or HIP compilers.") if(NOT CMAKE_RC_COMPILER_INIT) # Check if rc is already in the path @@ -183,13 +206,17 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" unset(__RC_COMPILER_PATH CACHE) endif() - if ( "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" OR "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" ) + if ( "x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" + OR "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC" + OR "x${CMAKE_HIP_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC") + include(Platform/Windows-MSVC) # Set the clang option forwarding prefix for clang-cl usage in the llvm-rc processing stage __enable_llvm_rc_preprocessing("-clang:" "") macro(__windows_compiler_clang_base lang) set(_COMPILE_${lang} "${_COMPILE_${lang}_MSVC}") __windows_compiler_msvc(${lang}) + unset(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue) # -ZI not supported by Clang set(CMAKE_${lang}_COMPILE_OPTIONS_WARNING_AS_ERROR "-WX") set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-imsvc") endmacro() @@ -202,6 +229,14 @@ if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC" endif() unset(__WINDOWS_CLANG_CMP0091) + cmake_policy(GET CMP0141 __WINDOWS_MSVC_CMP0141) + if(__WINDOWS_MSVC_CMP0141 STREQUAL "NEW") + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT "$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>") + else() + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT "") + endif() + unset(__WINDOWS_MSVC_CMP0141) + set(CMAKE_BUILD_TYPE_INIT Debug) __enable_llvm_rc_preprocessing("" "-x c") diff --git a/Modules/Platform/Windows-Intel-C.cmake b/Modules/Platform/Windows-Intel-C.cmake index e4d9b93..8ae6852 100644 --- a/Modules/Platform/Windows-Intel-C.cmake +++ b/Modules/Platform/Windows-Intel-C.cmake @@ -19,9 +19,8 @@ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) set(CMAKE_C_DEPENDS_USE_COMPILER TRUE) endif() -if("${CMAKE_SOURCE_DIR}${CMAKE_BINARY_DIR}" MATCHES " ") - # The Intel compiler does not properly escape spaces in a depfile. - # Fall back to msvc depfile format. - set(CMAKE_DEPFILE_FLAGS_C "/showIncludes") - set(CMAKE_C_DEPFILE_FORMAT msvc) -endif() +# The Intel compiler does not properly escape spaces in a depfile which can +# occur in source and binary cmake paths as well as external include paths. +# Until Intel fixes this bug, fall back unconditionally to msvc depfile format. +set(CMAKE_DEPFILE_FLAGS_C "/showIncludes") +set(CMAKE_C_DEPFILE_FORMAT msvc) diff --git a/Modules/Platform/Windows-Intel-CXX.cmake b/Modules/Platform/Windows-Intel-CXX.cmake index 6adbb6e..e2fa2af 100644 --- a/Modules/Platform/Windows-Intel-CXX.cmake +++ b/Modules/Platform/Windows-Intel-CXX.cmake @@ -20,9 +20,8 @@ if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER) set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE) endif() -if("${CMAKE_SOURCE_DIR}${CMAKE_BINARY_DIR}" MATCHES " ") - # The Intel compiler does not properly escape spaces in a depfile. - # Fall back to msvc depfile format. - set(CMAKE_DEPFILE_FLAGS_CXX "/showIncludes") - set(CMAKE_CXX_DEPFILE_FORMAT msvc) -endif() +# The Intel compiler does not properly escape spaces in a depfile which can +# occur in source and binary cmake paths as well as external include paths. +# Until Intel fixes this bug, fall back unconditionally to msvc depfile format. +set(CMAKE_DEPFILE_FLAGS_CXX "/showIncludes") +set(CMAKE_CXX_DEPFILE_FORMAT msvc) diff --git a/Modules/Platform/Windows-Intel-Fortran.cmake b/Modules/Platform/Windows-Intel-Fortran.cmake index e3804fb..c9b70d5 100644 --- a/Modules/Platform/Windows-Intel-Fortran.cmake +++ b/Modules/Platform/Windows-Intel-Fortran.cmake @@ -33,6 +33,8 @@ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -th set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -threads -libs:dll) set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -threads -libs:static -dbglibs) set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -threads -libs:dll -dbglibs) +set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -Z7) +set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase -Zi) # Intel Fortran for Windows supports single-threaded RTL but it is # not implemented by the Visual Studio integration. diff --git a/Modules/Platform/Windows-IntelLLVM-Fortran.cmake b/Modules/Platform/Windows-IntelLLVM-Fortran.cmake index 06d0a00..202ba23 100644 --- a/Modules/Platform/Windows-IntelLLVM-Fortran.cmake +++ b/Modules/Platform/Windows-IntelLLVM-Fortran.cmake @@ -33,6 +33,8 @@ set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -th set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -threads -libs:dll) set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -threads -libs:static -dbglibs) set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -threads -libs:dll -dbglibs) +set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -Z7) +set(CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase -Zi) # Intel Fortran for Windows supports single-threaded RTL but it is # not implemented by the Visual Studio integration. diff --git a/Modules/Platform/Windows-IntelLLVM.cmake b/Modules/Platform/Windows-IntelLLVM.cmake index f24dcdb..43f5874 100644 --- a/Modules/Platform/Windows-IntelLLVM.cmake +++ b/Modules/Platform/Windows-IntelLLVM.cmake @@ -3,26 +3,61 @@ # This module is shared by multiple languages; use include blocker. -if(__WINDOWS_INTEL) +if(__WINDOWS_INTEL_LLVM) return() endif() -set(__WINDOWS_INTEL 1) +set(__WINDOWS_INTEL_LLVM 1) +# Platform/Windows-MSVC adds some linking options icx/ifx do not understand, +# but that need to be passed to the linker. Wrap all the linking options from +# Platform/Windows-MSVC so that the compiler will hand them off to the linker +# without interpreting them. + +# Save original CMAKE_${t}_LINKER_FLAGS_INIT +foreach(t EXE SHARED MODULE STATIC) + set(_saved_cmake_${t}_linker_flags_init ${CMAKE_${t}_LINKER_FLAGS_INIT}) + set(CMAKE_${t}_LINKER_FLAGS_INIT "") +endforeach() include(Platform/Windows-MSVC) +# Wrap linker flags from Windows-MSVC +set(_IntelLLVM_LINKER_WRAPPER_FLAG "/Qoption,link,") +set(_IntelLLVM_LINKER_WRAPPER_FLAG_SEP ",") +foreach(t EXE SHARED MODULE STATIC) + set(_wrapped_linker_flags "") + foreach(flag ${CMAKE_${t}_LINKER_FLAGS_INIT}) + string(STRIP ${flag} flag) + list(APPEND _wrapped_linker_flags "${_IntelLLVM_LINKER_WRAPPER_FLAG}${flag}") + endforeach() + set(CMAKE_${t}_LINKER_FLAGS_INIT "") + list(APPEND CMAKE_${t}_LINKER_FLAGS_INIT + ${_saved_cmake_${t}_linker_flags_init} ${_wrapped_linker_flags}) +endforeach() + macro(__windows_compiler_intel lang) __windows_compiler_msvc(${lang}) - # For DPCPP other offload cases, some link flags need to go to the compiler - # driver and others need to go to the linker. Pass the compiler linking flags - # in CMAKE_${lang}_LINK_FLAGS and linker flags in LINK_FLAGS + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG "${_IntelLLVM_LINKER_WRAPPER_FLAG}") + set(CMAKE_${lang}_LINKER_WRAPPER_FLAG_SEP "${_IntelLLVM_LINKER_WRAPPER_FLAG_SEP}") + set(CMAKE_${lang}_CREATE_WIN32_EXE "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/subsystem:windows") + set(CMAKE_${lang}_CREATE_CONSOLE_EXE "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/subsystem:console") + set(CMAKE_LINK_DEF_FILE_FLAG "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/DEF:") + set(CMAKE_LIBRARY_PATH_FLAG "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/LIBPATH:") + + # Features for LINK_LIBRARY generator expression + if(MSVC_VERSION GREATER "1900") + ## WHOLE_ARCHIVE: Force loading all members of an archive + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE "LINKER:/WHOLEARCHIVE:<LIBRARY>") + set(CMAKE_LINK_LIBRARY_USING_WHOLE_ARCHIVE_SUPPORTED TRUE) + endif() + set(CMAKE_${lang}_LINK_EXECUTABLE - "${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} /link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${CMAKE_END_TEMP_FILE}") + "${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <LINK_LIBRARIES> /link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}") set(CMAKE_${lang}_CREATE_SHARED_LIBRARY - "${_CMAKE_VS_LINK_DLL}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -LD -link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}") + "${_CMAKE_VS_LINK_DLL}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -LD <LINK_FLAGS> <LINK_LIBRARIES> -link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}") if (NOT "${lang}" STREQUAL "Fortran" OR CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 2022.1) # The Fortran driver does not support -fuse-ld=llvm-lib before compiler version 2022.1 set(CMAKE_${lang}_CREATE_STATIC_LIBRARY - "<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -fuse-ld=llvm-lib -o <TARGET> -link <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}") + "<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -fuse-ld=llvm-lib -o <TARGET> <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}") endif() set(CMAKE_DEPFILE_FLAGS_${lang} "-QMD -QMT <DEP_TARGET> -QMF <DEP_FILE>") diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index e74ec9e..8e96bf4 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -331,6 +331,13 @@ else() endif() unset(__WINDOWS_MSVC_CMP0091) +cmake_policy(GET CMP0141 __WINDOWS_MSVC_CMP0141) +if(__WINDOWS_MSVC_CMP0141 STREQUAL "NEW") + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT "$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>") +else() + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT "") +endif() +unset(__WINDOWS_MSVC_CMP0141) # Features for LINK_LIBRARY generator expression if(MSVC_VERSION GREATER "1900") @@ -441,6 +448,12 @@ macro(__windows_compiler_msvc lang) endif() unset(_cmp0092) + if(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT) + set(_Zi "") + else() + set(_Zi " /Zi") + endif() + if(CMAKE_VS_PLATFORM_TOOLSET MATCHES "v[0-9]+_clang_.*") # note: MSVC 14 2015 Update 1 sets -fno-ms-compatibility by default, but this does not allow one to compile many projects # that include MS's own headers. CMake itself is affected project too. @@ -451,20 +464,24 @@ macro(__windows_compiler_msvc lang) string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT "${_MD} -DNDEBUG") # TODO: Add '-Os' once VS generator maps it properly for Clang else() string(APPEND CMAKE_${lang}_FLAGS_INIT " ${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_${lang}} /D_WINDOWS${_W3}${_FLAGS_${lang}}") - string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd} /Zi /Ob0 /Od ${_RTC1}") + string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT "${_MDd}${_Zi} /Ob0 /Od ${_RTC1}") string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT "${_MD} /O2 /Ob2 /DNDEBUG") - string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT "${_MD} /Zi /O2 /Ob1 /DNDEBUG") + string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT "${_MD}${_Zi} /O2 /Ob1 /DNDEBUG") string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT "${_MD} /O1 /Ob1 /DNDEBUG") endif() unset(_Wall) unset(_W3) unset(_MDd) unset(_MD) + unset(_Zi) set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -MT) set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -MD) set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -MTd) set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -MDd) + set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -Z7) + set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase -Zi) + set(CMAKE_${lang}_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue -ZI) endif() set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON) diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake index 6c1699b..326e715 100644 --- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake +++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake @@ -57,6 +57,12 @@ else() set(_MD "-MD ") endif() +if(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT) + set(_Zi "") +else() + set(_Zi " -Zi") +endif() + cmake_policy(GET CMP0092 _cmp0092) if(_cmp0092 STREQUAL "NEW") set(_W3 "") @@ -66,11 +72,12 @@ endif() unset(_cmp0092) string(APPEND CMAKE_CUDA_FLAGS_INIT " ${PLATFORM_DEFINES_CUDA} -D_WINDOWS -Xcompiler=\"${_W3}${_FLAGS_CXX}\"") -string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"${_MDd}-Zi -Ob0 -Od ${_RTC1}\"") +string(APPEND CMAKE_CUDA_FLAGS_DEBUG_INIT " -Xcompiler=\"${_MDd}${_Zi} -Ob0 -Od ${_RTC1}\"") string(APPEND CMAKE_CUDA_FLAGS_RELEASE_INIT " -Xcompiler=\"${_MD}-O2 -Ob2\" -DNDEBUG") -string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=\"${_MD}-Zi -O2 -Ob1\" -DNDEBUG") +string(APPEND CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT " -Xcompiler=\"${_MD}${_Zi} -O2 -Ob1\" -DNDEBUG") string(APPEND CMAKE_CUDA_FLAGS_MINSIZEREL_INIT " -Xcompiler=\"${_MD}-O1 -Ob1\" -DNDEBUG") unset(_W3) +unset(_Zi) unset(_MDd) unset(_MD) @@ -78,6 +85,9 @@ set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreaded -Xcomp set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDLL -Xcompiler=-MD) set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebug -Xcompiler=-MTd) set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY_MultiThreadedDebugDLL -Xcompiler=-MDd) +set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded -Xcompiler=-Z7) +set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase -Xcompiler=-Zi) +set(CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue -Xcompiler=-ZI) set(CMAKE_CUDA_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}") diff --git a/Modules/Platform/Windows.cmake b/Modules/Platform/Windows.cmake index d8b3957..5263161 100644 --- a/Modules/Platform/Windows.cmake +++ b/Modules/Platform/Windows.cmake @@ -19,8 +19,8 @@ set(CMAKE_LINK_LIBRARY_SUFFIX ".lib") set(CMAKE_DL_LIBS "") set(CMAKE_EXTRA_LINK_EXTENSIONS ".targets") -set(CMAKE_FIND_LIBRARY_PREFIXES "") -set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib") +set(CMAKE_FIND_LIBRARY_PREFIXES "" "lib") +set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".a") # for borland make long command lines are redirected to a file # with the following syntax, see Windows-bcc32.cmake for use diff --git a/Modules/Platform/kFreeBSD.cmake b/Modules/Platform/kFreeBSD.cmake index c1db259..09c240d 100644 --- a/Modules/Platform/kFreeBSD.cmake +++ b/Modules/Platform/kFreeBSD.cmake @@ -1,4 +1,5 @@ -# kFreeBSD looks just like Linux. +# kFreeBSD is a Debian GNU distribution with a kernel from FreeBSD, +# and should be marked as LINUX include(Platform/Linux) set(CMAKE_LIBRARY_ARCHITECTURE_REGEX "[a-z0-9_]+(-[a-z0-9_]+)?-kfreebsd-gnu[a-z0-9_]*") diff --git a/Modules/TestBigEndian.cmake b/Modules/TestBigEndian.cmake index ea8ca73..096c90c 100644 --- a/Modules/TestBigEndian.cmake +++ b/Modules/TestBigEndian.cmake @@ -77,20 +77,16 @@ macro(__TEST_BIG_ENDIAN_LEGACY_IMPL VARIABLE) endif() if(_test_language STREQUAL "CXX") - set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.cpp") + set(_test_file TestEndianess.cpp) else() - set(_test_file "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/TestEndianess.c") + set(_test_file TestEndianess.c) endif() - configure_file("${CMAKE_ROOT}/Modules/TestEndianess.c.in" - ${_test_file} - @ONLY) - - file(READ ${_test_file} TEST_ENDIANESS_FILE_CONTENT) + file(READ "${CMAKE_ROOT}/Modules/TestEndianess.c.in" TEST_ENDIANESS_FILE_CONTENT) + string(CONFIGURE "${TEST_ENDIANESS_FILE_CONTENT}" TEST_ENDIANESS_FILE_CONTENT @ONLY) try_compile(HAVE_${VARIABLE} - "${CMAKE_BINARY_DIR}" - ${_test_file} + SOURCE_FROM_VAR "${_test_file}" TEST_ENDIANESS_FILE_CONTENT OUTPUT_VARIABLE OUTPUT COPY_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/TestEndianess.bin" ) @@ -131,12 +127,12 @@ macro(__TEST_BIG_ENDIAN_LEGACY_IMPL VARIABLE) endif() file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log - "Determining if the system is big endian passed with the following output:\n${OUTPUT}\nTestEndianess.c:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n") + "Determining if the system is big endian passed with the following output:\n${OUTPUT}\n${_test_file}:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n") else() message(CHECK_FAIL "failed") file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if the system is big endian failed with the following output:\n${OUTPUT}\nTestEndianess.c:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n") + "Determining if the system is big endian failed with the following output:\n${OUTPUT}\n${_test_file}:\n${TEST_ENDIANESS_FILE_CONTENT}\n\n") set(${VARIABLE}) endif() endif() diff --git a/Modules/TestCXXAcceptsFlag.cmake b/Modules/TestCXXAcceptsFlag.cmake index ce505f3..2e511ae 100644 --- a/Modules/TestCXXAcceptsFlag.cmake +++ b/Modules/TestCXXAcceptsFlag.cmake @@ -25,8 +25,7 @@ macro(CHECK_CXX_ACCEPTS_FLAG FLAGS VARIABLE) if(NOT DEFINED ${VARIABLE}) message(CHECK_START "Checking to see if CXX compiler accepts flag ${FLAGS}") try_compile(${VARIABLE} - ${CMAKE_BINARY_DIR} - ${CMAKE_ROOT}/Modules/DummyCXXFile.cxx + SOURCES ${CMAKE_ROOT}/Modules/DummyCXXFile.cxx CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${FLAGS} OUTPUT_VARIABLE OUTPUT) if(${VARIABLE}) diff --git a/Modules/TestForANSIForScope.cmake b/Modules/TestForANSIForScope.cmake index 0f2dc01..06db586 100644 --- a/Modules/TestForANSIForScope.cmake +++ b/Modules/TestForANSIForScope.cmake @@ -17,8 +17,8 @@ for-init-statement to the loop body. if(NOT DEFINED CMAKE_ANSI_FOR_SCOPE) message(CHECK_START "Check for ANSI scope") - try_compile(CMAKE_ANSI_FOR_SCOPE ${CMAKE_BINARY_DIR} - ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx + try_compile(CMAKE_ANSI_FOR_SCOPE + SOURCES ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUTPUT) if (CMAKE_ANSI_FOR_SCOPE) message(CHECK_PASS "found") diff --git a/Modules/TestForSSTREAM.cmake b/Modules/TestForSSTREAM.cmake index 545b7ec..9a09ac7 100644 --- a/Modules/TestForSSTREAM.cmake +++ b/Modules/TestForSSTREAM.cmake @@ -16,8 +16,8 @@ check if the compiler supports the standard ANSI sstream header if(NOT DEFINED CMAKE_HAS_ANSI_STRING_STREAM) message(CHECK_START "Check for sstream") - try_compile(CMAKE_HAS_ANSI_STRING_STREAM ${CMAKE_BINARY_DIR} - ${CMAKE_ROOT}/Modules/TestForSSTREAM.cxx + try_compile(CMAKE_HAS_ANSI_STRING_STREAM + SOURCES ${CMAKE_ROOT}/Modules/TestForSSTREAM.cxx OUTPUT_VARIABLE OUTPUT) if (CMAKE_HAS_ANSI_STRING_STREAM) message(CHECK_PASS "found") diff --git a/Modules/TestForSTDNamespace.cmake b/Modules/TestForSTDNamespace.cmake index d101c83..cd9c782 100644 --- a/Modules/TestForSTDNamespace.cmake +++ b/Modules/TestForSTDNamespace.cmake @@ -16,8 +16,8 @@ check if the compiler supports std:: on stl classes if(NOT DEFINED CMAKE_STD_NAMESPACE) message(CHECK_START "Check for STD namespace") - try_compile(CMAKE_STD_NAMESPACE ${CMAKE_BINARY_DIR} - ${CMAKE_ROOT}/Modules/TestForSTDNamespace.cxx + try_compile(CMAKE_STD_NAMESPACE + SOURCES ${CMAKE_ROOT}/Modules/TestForSTDNamespace.cxx OUTPUT_VARIABLE OUTPUT) if (CMAKE_STD_NAMESPACE) message(CHECK_PASS "found") diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 35b1704..fd6596b 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -377,6 +377,7 @@ set(SWIG_EXTRA_LIBRARIES "") set(SWIG_PYTHON_EXTRA_FILE_EXTENSIONS ".py") set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java") set(SWIG_CSHARP_EXTRA_FILE_EXTENSIONS ".cs" "PINVOKE.cs") +set(SWIG_PERL_EXTRA_FILE_EXTENSIONS ".pm") set(SWIG_MANAGE_SUPPORT_FILES_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/UseSWIG/ManageSupportFiles.cmake") @@ -989,6 +990,9 @@ function(SWIG_ADD_LIBRARY name) endif() set_target_properties (${target_name} PROPERTIES PREFIX "") endif() + if (APPLE) + set_target_properties (${target_name} PROPERTIES SUFFIX ".dylib") + endif () else() # assume empty prefix because we expect the module to be dynamically loaded set_target_properties (${target_name} PROPERTIES PREFIX "") diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 95b07cb..c268a92 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -4,7 +4,7 @@ # To ensure maximum portability across various compilers and platforms # deactivate any compiler extensions. Skip this for QNX, where additional # work is needed to build without compiler extensions. -if (NOT CMAKE_SYSTEM_NAME STREQUAL "QNX") +if(NOT CMAKE_SYSTEM_NAME STREQUAL "QNX") set(CMAKE_C_EXTENSIONS FALSE) set(CMAKE_CXX_EXTENSIONS FALSE) endif() @@ -31,70 +31,48 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX") set(CMake_USE_XCOFF_PARSER 1) endif() +# Watcom support +if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") + set(CMAKE_USE_WMAKE 1) +endif() + +set(CMake_STAT_HAS_ST_MTIM ${KWSYS_CXX_STAT_HAS_ST_MTIM_COMPILED}) +set(CMake_STAT_HAS_ST_MTIMESPEC ${KWSYS_CXX_STAT_HAS_ST_MTIMESPEC_COMPILED}) + set(EXECUTABLE_OUTPUT_PATH ${CMake_BIN_DIR}) if(WIN32) # ensure Unicode friendly APIs are used on Windows - add_definitions(-DUNICODE -D_UNICODE) + add_compile_definitions(UNICODE _UNICODE) # minimize windows.h content - add_definitions(-DWIN32_LEAN_AND_MEAN) + add_compile_definitions(WIN32_LEAN_AND_MEAN) endif() # configure the .dox.in file if(CMake_BUILD_DEVELOPER_REFERENCE) - configure_file( - "${CMake_SOURCE_DIR}/Source/dir.dox.in" - "${CMake_BINARY_DIR}/Source/dir.dox" - @ONLY - ) + configure_file(dir.dox.in dir.dox @ONLY) endif() # configure the .h file -configure_file( - "${CMake_SOURCE_DIR}/Source/cmConfigure.cmake.h.in" - "${CMake_BINARY_DIR}/Source/cmConfigure.h" - ) -configure_file( - "${CMake_SOURCE_DIR}/Source/cmVersionConfig.h.in" - "${CMake_BINARY_DIR}/Source/cmVersionConfig.h" - ) -configure_file( - "${CMake_SOURCE_DIR}/Source/CPack/cmCPackConfigure.h.in" - "${CMake_BINARY_DIR}/Source/CPack/cmCPackConfigure.h" - ) +configure_file(cmConfigure.cmake.h.in cmConfigure.h) +configure_file(cmVersionConfig.h.in cmVersionConfig.h) # Tell CMake executable in the build tree where to find the source tree. configure_file( - "${CMake_SOURCE_DIR}/Source/CMakeSourceDir.txt.in" - "${CMake_BINARY_DIR}/CMakeFiles/CMakeSourceDir.txt" @ONLY - ) - -# add the include path to find the .h -include_directories( - "${CMake_BINARY_DIR}/Source" - "${CMake_SOURCE_DIR}/Source" - "${CMake_SOURCE_DIR}/Source/LexerParser" - ${CMAKE_ZLIB_INCLUDES} - ${CMAKE_EXPAT_INCLUDES} - ${CMAKE_TAR_INCLUDES} - ${CMake_HAIKU_INCLUDE_DIRS} + CMakeSourceDir.txt.in + "${CMake_BINARY_DIR}/CMakeFiles/CMakeSourceDir.txt" + @ONLY ) -# Check if we can build the Mach-O parser. -if(CMake_USE_MACH_PARSER) - set(MACH_SRCS cmMachO.h cmMachO.cxx) -endif() - -# Check if we can build the XCOFF parser. -if(CMake_USE_XCOFF_PARSER) - set(XCOFF_SRCS cmXCOFF.h cmXCOFF.cxx) -endif() +# Add a dummy library and add sources later depends on condition +add_library(ManifestLib INTERFACE) # -# Sources for CMakeLib +# create a library used by the command line and the GUI # -set(SRCS +add_library( + CMakeLib # Lexers/Parsers LexerParser/cmCommandArgumentLexer.cxx LexerParser/cmCommandArgumentLexer.h @@ -168,7 +146,9 @@ set(SRCS cmCMakePresetsGraphReadJSON.cxx cmCMakePresetsGraphReadJSONBuildPresets.cxx cmCMakePresetsGraphReadJSONConfigurePresets.cxx + cmCMakePresetsGraphReadJSONPackagePresets.cxx cmCMakePresetsGraphReadJSONTestPresets.cxx + cmCMakePresetsGraphReadJSONWorkflowPresets.cxx cmCommandArgumentParserHelper.cxx cmCommonTargetGenerator.cxx cmCommonTargetGenerator.h @@ -197,6 +177,8 @@ set(SRCS cmCustomCommandLines.cxx cmCustomCommandLines.h cmCustomCommandTypes.h + cmCxxModuleMapper.cxx + cmCxxModuleMapper.h cmDefinitions.cxx cmDefinitions.h cmDependencyProvider.h @@ -367,7 +349,6 @@ set(SRCS cmRulePlaceholderExpander.h cmLocalUnixMakefileGenerator3.cxx cmLocale.h - ${MACH_SRCS} cmMakefile.cxx cmMakefile.h cmMakefileTargetGenerator.cxx @@ -467,7 +448,6 @@ set(SRCS cmWorkerPool.h cmWorkingDirectory.cxx cmWorkingDirectory.h - ${XCOFF_SRCS} cmXMLParser.cxx cmXMLParser.h cmXMLSafe.cxx @@ -543,6 +523,8 @@ set(SRCS cmExecuteProcessCommand.h cmExpandedCommandArgument.cxx cmExpandedCommandArgument.h + cmExperimental.cxx + cmExperimental.h cmExportCommand.cxx cmExportCommand.h cmExportLibraryDependenciesCommand.cxx @@ -567,6 +549,8 @@ set(SRCS cmFindProgramCommand.h cmForEachCommand.cxx cmForEachCommand.h + cmBlockCommand.cxx + cmBlockCommand.h cmFunctionBlocker.cxx cmFunctionBlocker.h cmFunctionCommand.cxx @@ -603,6 +587,8 @@ set(SRCS cmInstallCommand.h cmInstallCommandArguments.cxx cmInstallCommandArguments.h + cmInstallCxxModuleBmiGenerator.cxx + cmInstallCxxModuleBmiGenerator.h cmInstallFilesCommand.cxx cmInstallFilesCommand.h cmInstallProgramsCommand.cxx @@ -721,6 +707,23 @@ set(SRCS cmWhileCommand.h cmWriteFileCommand.cxx cmWriteFileCommand.h + # Ninja support + cmScanDepFormat.cxx + cmGlobalNinjaGenerator.cxx + cmGlobalNinjaGenerator.h + cmNinjaTypes.h + cmLocalNinjaGenerator.cxx + cmLocalNinjaGenerator.h + cmNinjaTargetGenerator.cxx + cmNinjaTargetGenerator.h + cmNinjaNormalTargetGenerator.cxx + cmNinjaNormalTargetGenerator.h + cmNinjaUtilityTargetGenerator.cxx + cmNinjaUtilityTargetGenerator.h + cmNinjaLinkLineComputer.cxx + cmNinjaLinkLineComputer.h + cmNinjaLinkLineDeviceComputer.cxx + cmNinjaLinkLineDeviceComputer.h cm_get_date.h cm_get_date.c @@ -734,102 +737,152 @@ set(SRCS bindexplib.cxx ) +target_include_directories( + CMakeLib + PUBLIC + # add the include path to find the .h + "${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/LexerParser" + ${CMake_HAIKU_INCLUDE_DIRS} + ) +target_link_libraries( + CMakeLib + PUBLIC + cmstd + cmsys + CURL::libcurl + EXPAT::EXPAT + JsonCpp::JsonCpp + $<TARGET_NAME_IF_EXISTS:kwiml::kwiml> + LibArchive::LibArchive + LibRHash::LibRHash + LibUV::LibUV + Threads::Threads + ZLIB::ZLIB + ) -SET_PROPERTY(SOURCE cmProcessOutput.cxx cmWindowsRegistry.cxx APPEND PROPERTY COMPILE_DEFINITIONS - KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) +# Check if we can build the Mach-O parser. +if(CMake_USE_MACH_PARSER) + target_sources( + CMakeLib + PRIVATE + cmMachO.h + cmMachO.cxx + ) +endif() + +# Check if we can build the XCOFF parser. +if(CMake_USE_XCOFF_PARSER) + target_sources( + CMakeLib + PRIVATE + cmXCOFF.h + cmXCOFF.cxx + ) +endif() # Xcode only works on Apple if(APPLE) - set(SRCS ${SRCS} - cmXCodeObject.cxx - cmXCode21Object.cxx - cmXCodeScheme.cxx - cmGlobalXCodeGenerator.cxx - cmGlobalXCodeGenerator.h - cmLocalXCodeGenerator.cxx - cmLocalXCodeGenerator.h) + target_sources( + CMakeLib + PRIVATE + cmXCodeObject.cxx + cmXCode21Object.cxx + cmXCodeScheme.cxx + cmGlobalXCodeGenerator.cxx + cmGlobalXCodeGenerator.h + cmLocalXCodeGenerator.cxx + cmLocalXCodeGenerator.h + ) endif() - -if (WIN32) - set(SRCS ${SRCS} - cmCallVisualStudioMacro.cxx - cmCallVisualStudioMacro.h +if(WIN32) + target_sources( + CMakeLib + PRIVATE + cmCallVisualStudioMacro.cxx + cmCallVisualStudioMacro.h ) if(NOT UNIX) - set(SRCS ${SRCS} - cmGlobalBorlandMakefileGenerator.cxx - cmGlobalBorlandMakefileGenerator.h - cmGlobalMSYSMakefileGenerator.cxx - cmGlobalMinGWMakefileGenerator.cxx - cmGlobalNMakeMakefileGenerator.cxx - cmGlobalNMakeMakefileGenerator.h - cmGlobalJOMMakefileGenerator.cxx - cmGlobalJOMMakefileGenerator.h - cmGlobalVisualStudio71Generator.cxx - cmGlobalVisualStudio71Generator.h - cmGlobalVisualStudio7Generator.cxx - cmGlobalVisualStudio7Generator.h - cmGlobalVisualStudio8Generator.cxx - cmGlobalVisualStudio8Generator.h - cmGlobalVisualStudio9Generator.cxx - cmGlobalVisualStudio9Generator.h - cmVisualStudioGeneratorOptions.h - cmVisualStudioGeneratorOptions.cxx - cmVsProjectType.h - cmVisualStudio10TargetGenerator.h - cmVisualStudio10TargetGenerator.cxx - cmLocalVisualStudio10Generator.cxx - cmLocalVisualStudio10Generator.h - cmGlobalVisualStudio10Generator.h - cmGlobalVisualStudio10Generator.cxx - cmGlobalVisualStudio11Generator.h - cmGlobalVisualStudio11Generator.cxx - cmGlobalVisualStudio12Generator.h - cmGlobalVisualStudio12Generator.cxx - cmGlobalVisualStudio14Generator.h - cmGlobalVisualStudio14Generator.cxx - cmGlobalVisualStudioGenerator.cxx - cmGlobalVisualStudioGenerator.h - cmGlobalVisualStudioVersionedGenerator.h - cmGlobalVisualStudioVersionedGenerator.cxx - cmIDEFlagTable.h - cmIDEOptions.cxx - cmIDEOptions.h - cmLocalVisualStudio7Generator.cxx - cmLocalVisualStudio7Generator.h - cmLocalVisualStudioGenerator.cxx - cmLocalVisualStudioGenerator.h - cmVisualStudioSlnData.h - cmVisualStudioSlnData.cxx - cmVisualStudioSlnParser.h - cmVisualStudioSlnParser.cxx - cmVisualStudioWCEPlatformParser.h - cmVisualStudioWCEPlatformParser.cxx - cmVSSetupHelper.cxx - cmVSSetupHelper.h + target_sources( + CMakeLib + PRIVATE + cmGlobalBorlandMakefileGenerator.cxx + cmGlobalBorlandMakefileGenerator.h + cmGlobalMSYSMakefileGenerator.cxx + cmGlobalMinGWMakefileGenerator.cxx + cmGlobalNMakeMakefileGenerator.cxx + cmGlobalNMakeMakefileGenerator.h + cmGlobalJOMMakefileGenerator.cxx + cmGlobalJOMMakefileGenerator.h + cmGlobalVisualStudio71Generator.cxx + cmGlobalVisualStudio71Generator.h + cmGlobalVisualStudio7Generator.cxx + cmGlobalVisualStudio7Generator.h + cmGlobalVisualStudio8Generator.cxx + cmGlobalVisualStudio8Generator.h + cmGlobalVisualStudio9Generator.cxx + cmGlobalVisualStudio9Generator.h + cmVisualStudioGeneratorOptions.h + cmVisualStudioGeneratorOptions.cxx + cmVsProjectType.h + cmVisualStudio10TargetGenerator.h + cmVisualStudio10TargetGenerator.cxx + cmLocalVisualStudio10Generator.cxx + cmLocalVisualStudio10Generator.h + cmGlobalVisualStudio10Generator.h + cmGlobalVisualStudio10Generator.cxx + cmGlobalVisualStudio11Generator.h + cmGlobalVisualStudio11Generator.cxx + cmGlobalVisualStudio12Generator.h + cmGlobalVisualStudio12Generator.cxx + cmGlobalVisualStudio14Generator.h + cmGlobalVisualStudio14Generator.cxx + cmGlobalVisualStudioGenerator.cxx + cmGlobalVisualStudioGenerator.h + cmGlobalVisualStudioVersionedGenerator.h + cmGlobalVisualStudioVersionedGenerator.cxx + cmIDEFlagTable.h + cmIDEOptions.cxx + cmIDEOptions.h + cmLocalVisualStudio7Generator.cxx + cmLocalVisualStudio7Generator.h + cmLocalVisualStudioGenerator.cxx + cmLocalVisualStudioGenerator.h + cmVisualStudioSlnData.h + cmVisualStudioSlnData.cxx + cmVisualStudioSlnParser.h + cmVisualStudioSlnParser.cxx + cmVisualStudioWCEPlatformParser.h + cmVisualStudioWCEPlatformParser.cxx + cmVSSetupHelper.cxx + cmVSSetupHelper.h ) # Add a manifest file to executables on Windows to allow for # GetVersion to work properly on Windows 8 and above. - set(MANIFEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/cmake.version.manifest) + target_sources(ManifestLib INTERFACE cmake.version.manifest) endif() -endif () +endif() # Watcom support -if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") - set_property(SOURCE cmake.cxx APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_USE_WMAKE) - list(APPEND SRCS - cmGlobalWatcomWMakeGenerator.cxx - cmGlobalWatcomWMakeGenerator.h +if(CMAKE_USE_WMAKE) + target_sources( + CMakeLib + PRIVATE + cmGlobalWatcomWMakeGenerator.cxx + cmGlobalWatcomWMakeGenerator.h ) endif() # GHS support # Works only for windows and linux if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(SRCS ${SRCS} + target_sources( + CMakeLib + PRIVATE cmGlobalGhsMultiGenerator.cxx cmGlobalGhsMultiGenerator.h cmLocalGhsMultiGenerator.cxx @@ -841,104 +894,45 @@ if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Linux") ) endif() - -# Ninja support -set(SRCS ${SRCS} - cmScanDepFormat.cxx - cmGlobalNinjaGenerator.cxx - cmGlobalNinjaGenerator.h - cmNinjaTypes.h - cmLocalNinjaGenerator.cxx - cmLocalNinjaGenerator.h - cmNinjaTargetGenerator.cxx - cmNinjaTargetGenerator.h - cmNinjaNormalTargetGenerator.cxx - cmNinjaNormalTargetGenerator.h - cmNinjaUtilityTargetGenerator.cxx - cmNinjaUtilityTargetGenerator.h - cmNinjaLinkLineComputer.cxx - cmNinjaLinkLineComputer.h - cmNinjaLinkLineDeviceComputer.cxx - cmNinjaLinkLineDeviceComputer.h - ) - # Temporary variable for tools targets set(_tools) if(WIN32 AND NOT CYGWIN) set_source_files_properties(cmcldeps.cxx PROPERTIES COMPILE_DEFINITIONS _WIN32_WINNT=0x0501) - add_executable(cmcldeps cmcldeps.cxx ${MANIFEST_FILE}) + add_executable(cmcldeps cmcldeps.cxx) + target_link_libraries(cmcldeps PRIVATE CMakeLib ManifestLib) list(APPEND _tools cmcldeps) - target_link_libraries(cmcldeps CMakeLib) endif() -foreach(v CURL_CA_BUNDLE CURL_CA_PATH) - if(${v}) - set_property(SOURCE cmCurl.cxx APPEND PROPERTY COMPILE_DEFINITIONS ${v}="${${v}}") - endif() -endforeach() - -foreach(check - STAT_HAS_ST_MTIM - STAT_HAS_ST_MTIMESPEC - ) - if(KWSYS_CXX_${check}_COMPILED) # abuse KWSys check cache entry - set(CMake_${check} 1) - else() - set(CMake_${check} 0) - endif() - set_property(SOURCE cmFileTime.cxx APPEND PROPERTY - COMPILE_DEFINITIONS CMake_${check}=${CMake_${check}}) -endforeach() - -# create a library used by the command line and the GUI -add_library(CMakeLib ${SRCS}) -target_link_libraries(CMakeLib cmsys - ${CMAKE_STD_LIBRARY} - ${CMAKE_EXPAT_LIBRARIES} ${CMAKE_ZLIB_LIBRARIES} - ${CMAKE_TAR_LIBRARIES} - ${CMAKE_CURL_LIBRARIES} - ${CMAKE_JSONCPP_LIBRARIES} - ${CMAKE_LIBUV_LIBRARIES} - ${CMAKE_LIBRHASH_LIBRARIES} - ${CMake_KWIML_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} - ) - if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "sparc") # the atomic instructions are implemented using libatomic on some platforms, # so linking to that may be required check_library_exists(atomic __atomic_fetch_add_4 "" LIBATOMIC_NEEDED) if(LIBATOMIC_NEEDED) - target_link_libraries(CMakeLib atomic) + target_link_libraries(CMakeLib PUBLIC atomic) endif() endif() # On Apple we need CoreFoundation and CoreServices if(APPLE) - target_link_libraries(CMakeLib "-framework CoreFoundation") - target_link_libraries(CMakeLib "-framework CoreServices") + target_link_libraries(CMakeLib PUBLIC "-framework CoreFoundation") + target_link_libraries(CMakeLib PUBLIC "-framework CoreServices") endif() if(WIN32 AND NOT UNIX) # We need the rpcrt4 library on Windows. # We need the crypt32 library on Windows for crypto/cert APIs. - target_link_libraries(CMakeLib rpcrt4 crypt32) + target_link_libraries(CMakeLib PUBLIC rpcrt4 crypt32) endif() target_compile_definitions(CMakeLib PUBLIC ${CLANG_TIDY_DEFINITIONS}) # -# CTestLib -# -include_directories( - "${CMake_SOURCE_DIR}/Source/CTest" - ${CMAKE_CURL_INCLUDES} - ) -# -# Sources for CTestLib +# Build CTestLib # -set(CTEST_SRCS cmCTest.cxx +add_library( + CTestLib + cmCTest.cxx CTest/cmProcess.cxx CTest/cmCTestBinPacker.cxx CTest/cmCTestBuildAndTestHandler.cxx @@ -1005,21 +999,18 @@ set(CTEST_SRCS cmCTest.cxx LexerParser/cmCTestResourceGroupsLexer.h LexerParser/cmCTestResourceGroupsLexer.in.l ) - -# Build CTestLib -add_library(CTestLib ${CTEST_SRCS}) -target_link_libraries(CTestLib CMakeLib ${CMAKE_CURL_LIBRARIES}) - -# -# CPack -# -include_directories( - "${CMake_SOURCE_DIR}/Source/CPack" +target_include_directories( + CTestLib + PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/CTest" ) +target_link_libraries(CTestLib PUBLIC CMakeLib) + # -# Sources for CPack +# Build CPackLib # -set(CPACK_SRCS +add_library( + CPackLib CPack/cmCPackArchiveGenerator.cxx CPack/cmCPackComponentGroup.cxx CPack/cmCPackDebGenerator.cxx @@ -1030,9 +1021,7 @@ set(CPACK_SRCS CPack/cmCPackNSISGenerator.cxx CPack/cmCPackNuGetGenerator.cxx CPack/cmCPackSTGZGenerator.cxx - ) -# CPack IFW generator -set(CPACK_SRCS ${CPACK_SRCS} + # CPack IFW generator CPack/IFW/cmCPackIFWCommon.cxx CPack/IFW/cmCPackIFWCommon.h CPack/IFW/cmCPackIFWGenerator.cxx @@ -1044,19 +1033,20 @@ set(CPACK_SRCS ${CPACK_SRCS} CPack/IFW/cmCPackIFWRepository.cxx CPack/IFW/cmCPackIFWRepository.h ) - -if(CYGWIN) - set(CPACK_SRCS ${CPACK_SRCS} - CPack/cmCPackCygwinBinaryGenerator.cxx - CPack/cmCPackCygwinSourceGenerator.cxx - ) -endif() +target_include_directories( + CPackLib + PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/CPack" + "${CMAKE_CURRENT_BINARY_DIR}/CPack" + ) +target_link_libraries(CPackLib PUBLIC CMakeLib) option(CPACK_ENABLE_FREEBSD_PKG "Add FreeBSD pkg(8) generator to CPack." OFF) - if(UNIX) - set(CPACK_SRCS ${CPACK_SRCS} - CPack/cmCPackRPMGenerator.cxx + target_sources( + CPackLib + PRIVATE + CPack/cmCPackRPMGenerator.cxx ) # Optionally, try to use pkg(8) @@ -1072,13 +1062,14 @@ if(UNIX) pkg DOC "FreeBSD pkg(8) library") if(FREEBSD_PKG_LIBRARIES) - set(CPACK_SRCS ${CPACK_SRCS} - CPack/cmCPackFreeBSDGenerator.cxx - ) + set(ENABLE_BUILD_FREEBSD_PKG 1) + target_sources(CPackLib PRIVATE CPack/cmCPackFreeBSDGenerator.cxx) + target_include_directories(CPackLib PUBLIC ${FREEBSD_PKG_INCLUDE_DIRS}) + target_link_libraries(CPackLib PUBLIC ${FREEBSD_PKG_LIBRARIES}) endif() endif() - if (NOT FREEBSD_PKG_INCLUDE_DIRS OR NOT FREEBSD_PKG_LIBRARIES) + if(NOT FREEBSD_PKG_INCLUDE_DIRS OR NOT FREEBSD_PKG_LIBRARIES) message(FATAL_ERROR "CPack needs libpkg(3) to produce FreeBSD packages natively.") endif() else() @@ -1088,47 +1079,57 @@ if(UNIX) endif() if(CYGWIN) + target_sources( + CPackLib + PRIVATE + CPack/cmCPackCygwinBinaryGenerator.cxx + CPack/cmCPackCygwinSourceGenerator.cxx + ) find_package(LibUUID) endif() -if(WIN32 OR (CYGWIN AND LibUUID_FOUND)) - set(CPACK_SRCS ${CPACK_SRCS} - CPack/WiX/cmCMakeToWixPath.cxx - CPack/WiX/cmCMakeToWixPath.h - CPack/WiX/cmCPackWIXGenerator.cxx - CPack/WiX/cmCPackWIXGenerator.h - CPack/WiX/cmWIXAccessControlList.cxx - CPack/WiX/cmWIXAccessControlList.h - CPack/WiX/cmWIXDirectoriesSourceWriter.cxx - CPack/WiX/cmWIXDirectoriesSourceWriter.h - CPack/WiX/cmWIXFeaturesSourceWriter.cxx - CPack/WiX/cmWIXFeaturesSourceWriter.h - CPack/WiX/cmWIXFilesSourceWriter.cxx - CPack/WiX/cmWIXFilesSourceWriter.h - CPack/WiX/cmWIXPatch.cxx - CPack/WiX/cmWIXPatch.h - CPack/WiX/cmWIXPatchParser.cxx - CPack/WiX/cmWIXPatchParser.h - CPack/WiX/cmWIXRichTextFormatWriter.cxx - CPack/WiX/cmWIXRichTextFormatWriter.h - CPack/WiX/cmWIXShortcut.cxx - CPack/WiX/cmWIXShortcut.h - CPack/WiX/cmWIXSourceWriter.cxx - CPack/WiX/cmWIXSourceWriter.h + +if(WIN32 OR (CYGWIN AND TARGET LibUUID::LibUUID)) + set(ENABLE_BUILD_WIX_GENERATOR 1) + target_sources( + CPackLib + PRIVATE + CPack/WiX/cmCMakeToWixPath.cxx + CPack/WiX/cmCMakeToWixPath.h + CPack/WiX/cmCPackWIXGenerator.cxx + CPack/WiX/cmCPackWIXGenerator.h + CPack/WiX/cmWIXAccessControlList.cxx + CPack/WiX/cmWIXAccessControlList.h + CPack/WiX/cmWIXDirectoriesSourceWriter.cxx + CPack/WiX/cmWIXDirectoriesSourceWriter.h + CPack/WiX/cmWIXFeaturesSourceWriter.cxx + CPack/WiX/cmWIXFeaturesSourceWriter.h + CPack/WiX/cmWIXFilesSourceWriter.cxx + CPack/WiX/cmWIXFilesSourceWriter.h + CPack/WiX/cmWIXPatch.cxx + CPack/WiX/cmWIXPatch.h + CPack/WiX/cmWIXPatchParser.cxx + CPack/WiX/cmWIXPatchParser.h + CPack/WiX/cmWIXRichTextFormatWriter.cxx + CPack/WiX/cmWIXRichTextFormatWriter.h + CPack/WiX/cmWIXShortcut.cxx + CPack/WiX/cmWIXShortcut.h + CPack/WiX/cmWIXSourceWriter.cxx + CPack/WiX/cmWIXSourceWriter.h ) + target_link_libraries(CPackLib PUBLIC $<TARGET_NAME_IF_EXISTS:LibUUID::LibUUID>) endif() if(APPLE) - set(CPACK_SRCS ${CPACK_SRCS} - CPack/cmCPackBundleGenerator.cxx - CPack/cmCPackDragNDropGenerator.cxx - CPack/cmCPackPKGGenerator.cxx - CPack/cmCPackProductBuildGenerator.cxx + target_sources( + CPackLib + PRIVATE + CPack/cmCPackBundleGenerator.cxx + CPack/cmCPackDragNDropGenerator.cxx + CPack/cmCPackPKGGenerator.cxx + CPack/cmCPackProductBuildGenerator.cxx ) endif() -# Build CPackLib -add_library(CPackLib ${CPACK_SRCS}) -target_link_libraries(CPackLib CMakeLib) if(APPLE) # Some compilers produce errors in the CoreServices framework headers. # Ideally such errors should be fixed by either the compiler vendor @@ -1136,8 +1137,7 @@ if(APPLE) # If it does not work, build with reduced functionality and warn. check_include_file("CoreServices/CoreServices.h" HAVE_CoreServices) if(HAVE_CoreServices) - set_property(SOURCE CPack/cmCPackDragNDropGenerator.cxx PROPERTY COMPILE_DEFINITIONS HAVE_CoreServices) - target_link_libraries(CPackLib "-framework CoreServices") + target_link_libraries(CPackLib PUBLIC "-framework CoreServices") else() message(WARNING "This compiler does not appear to support\n" " #include <CoreServices/CoreServices.h>\n" @@ -1145,31 +1145,25 @@ if(APPLE) "See CMakeFiles/CMakeError.log for details of the failure.") endif() endif() -if(CYGWIN AND LibUUID_FOUND) - target_link_libraries(CPackLib ${LibUUID_LIBRARIES}) - include_directories(CPackLib ${LibUUID_INCLUDE_DIRS}) - set_property(SOURCE CPack/cmCPackGeneratorFactory.cxx PROPERTY COMPILE_DEFINITIONS HAVE_LIBUUID) -endif() -if(CPACK_ENABLE_FREEBSD_PKG AND FREEBSD_PKG_INCLUDE_DIRS AND FREEBSD_PKG_LIBRARIES) - target_link_libraries(CPackLib ${FREEBSD_PKG_LIBRARIES}) - include_directories(${FREEBSD_PKG_INCLUDE_DIRS}) - add_definitions(-DHAVE_FREEBSD_PKG) -endif() + +# Render config header file for CPackLib +configure_file(CPack/cmCPackConfigure.h.in CPack/cmCPackConfigure.h) + # Build CMake executable -add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h ${MANIFEST_FILE}) +add_executable(cmake cmakemain.cxx cmcmd.cxx cmcmd.h) +target_link_libraries(cmake PRIVATE CMakeLib ManifestLib) list(APPEND _tools cmake) -target_link_libraries(cmake CMakeLib) # Build CTest executable -add_executable(ctest ctest.cxx ${MANIFEST_FILE}) +add_executable(ctest ctest.cxx) +target_link_libraries(ctest PRIVATE CTestLib ManifestLib) list(APPEND _tools ctest) -target_link_libraries(ctest CTestLib) # Build CPack executable -add_executable(cpack CPack/cpack.cxx ${MANIFEST_FILE}) +add_executable(cpack CPack/cpack.cxx) +target_link_libraries(cpack PRIVATE CPackLib ManifestLib) list(APPEND _tools cpack) -target_link_libraries(cpack CPackLib) # Curses GUI if(BUILD_CursesDialog) @@ -1182,8 +1176,8 @@ if(BUILD_QtDialog) add_subdirectory(QtDialog) endif() -include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL) -include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL) +include(${CMAKE_CURRENT_BINARY_DIR}/LocalUserOptions.cmake OPTIONAL) +include(${CMAKE_CURRENT_SOURCE_DIR}/LocalUserOptions.cmake OPTIONAL) if(WIN32) # Compute the binary version that appears in the RC file. Version @@ -1202,14 +1196,14 @@ if(WIN32) set(CMake_RCVERSION_STR ${CMake_VERSION}) # Add Windows executable version information. - configure_file("CMakeVersion.rc.in" "CMakeVersion.rc" @ONLY) + configure_file(CMakeVersion.rc.in CMakeVersion.rc @ONLY) # We use a separate object library for this to work around a limitation of # MinGW's windres tool with spaces in the path to the include directories. add_library(CMakeVersion OBJECT "${CMAKE_CURRENT_BINARY_DIR}/CMakeVersion.rc") set_property(TARGET CMakeVersion PROPERTY INCLUDE_DIRECTORIES "") - foreach(_tool ${_tools}) - target_sources(${_tool} PRIVATE $<TARGET_OBJECTS:CMakeVersion>) + foreach(_tool IN LISTS _tools) + target_link_libraries(${_tool} PRIVATE CMakeVersion) endforeach() endif() @@ -1220,7 +1214,7 @@ endif() # Install tools -foreach(_tool ${_tools}) +foreach(_tool IN LISTS _tools) CMake_OPTIONAL_COMPONENT(${_tool}) install(TARGETS ${_tool} DESTINATION ${CMAKE_BIN_DIR} ${COMPONENT}) endforeach() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 2d5e295..c51f421 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,15 +1,15 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) -set(CMake_VERSION_MINOR 24) -set(CMake_VERSION_PATCH 2) -#set(CMake_VERSION_RC 0) +set(CMake_VERSION_MINOR 25) +set(CMake_VERSION_PATCH 0) +set(CMake_VERSION_RC 2) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. set(CMake_VERSION "${CMake_VERSION_MAJOR}.${CMake_VERSION_MINOR}.${CMake_VERSION_PATCH}") if(DEFINED CMake_VERSION_RC) - set(CMake_VERSION "${CMake_VERSION}-rc${CMake_VERSION_RC}") + string(APPEND CMake_VERSION "-rc${CMake_VERSION_RC}") endif() # Releases define a small patch level. @@ -53,7 +53,7 @@ if(NOT CMake_VERSION_NO_GIT) # If this is not the exact commit of a release, add dev info. if(NOT "${git_subject}" MATCHES "^[Cc][Mm]ake ${CMake_VERSION}$") - set(CMake_VERSION "${CMake_VERSION}-g${git_hash}") + string(APPEND CMake_VERSION "-g${git_hash}") endif() # If this is a work tree, check whether it is dirty. @@ -68,7 +68,7 @@ if(NOT CMake_VERSION_NO_GIT) # No commit information. if(NOT CMake_VERSION_IS_RELEASE) # Generic development version. - set(CMake_VERSION "${CMake_VERSION}-git") + string(APPEND CMake_VERSION "-git") endif() endif() endif() @@ -80,5 +80,5 @@ else() set(CMake_VERSION_SUFFIX "") endif() if(CMake_VERSION_IS_DIRTY) - set(CMake_VERSION ${CMake_VERSION}-dirty) + string(APPEND CMake_VERSION "-dirty") endif() diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index 56e8463..894c24b 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -94,6 +94,18 @@ std::string cmCPackArchiveGenerator::GetArchiveComponentFileName( int cmCPackArchiveGenerator::InitializeInternal() { this->SetOptionIfNotSet("CPACK_INCLUDE_TOPLEVEL_DIRECTORY", "1"); + cmValue newExtensionValue = this->GetOption("CPACK_ARCHIVE_FILE_EXTENSION"); + if (!newExtensionValue.IsEmpty()) { + std::string newExtension = *newExtensionValue; + if (!cmHasLiteralPrefix(newExtension, ".")) { + newExtension = cmStrCat('.', newExtension); + } + cmCPackLogger(cmCPackLog::LOG_DEBUG, + "Using user-provided file extension " + << newExtension << " instead of the default " + << this->OutputExtension << std::endl); + this->OutputExtension = std::move(newExtension); + } return this->Superclass::InitializeInternal(); } diff --git a/Source/CPack/cmCPackConfigure.h.in b/Source/CPack/cmCPackConfigure.h.in index 8ac1661..2c1302d 100644 --- a/Source/CPack/cmCPackConfigure.h.in +++ b/Source/CPack/cmCPackConfigure.h.in @@ -1,2 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#cmakedefine01 ENABLE_BUILD_WIX_GENERATOR +#cmakedefine01 ENABLE_BUILD_FREEBSD_PKG +#cmakedefine01 HAVE_CoreServices diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx index 0f7acfb..0579066 100644 --- a/Source/CPack/cmCPackDragNDropGenerator.cxx +++ b/Source/CPack/cmCPackDragNDropGenerator.cxx @@ -14,6 +14,7 @@ #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" +#include "cmCPackConfigure.h" #include "cmCPackGenerator.h" #include "cmCPackLog.h" #include "cmDuration.h" @@ -23,7 +24,7 @@ #include "cmValue.h" #include "cmXMLWriter.h" -#ifdef HAVE_CoreServices +#if HAVE_CoreServices // For the old LocaleStringToLangAndRegionCodes() function, to convert // to the old Script Manager RegionCode values needed for the 'LPic' data // structure used for generating multi-lingual SLAs. @@ -590,7 +591,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, kCFStringEncodingMacRoman); LangCode lang = 0; RegionCode region = 0; -#ifdef HAVE_CoreServices +#if HAVE_CoreServices OSStatus err = LocaleStringToLangAndRegionCodes(iso_language_cstr, &lang, ®ion); if (err != noErr) @@ -601,7 +602,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir, << iso_language_cstr << std::endl); return 0; } -#ifdef HAVE_CoreServices +#if HAVE_CoreServices header_data.push_back(region); header_data.push_back(i); header_data.push_back(0); diff --git a/Source/CPack/cmCPackFreeBSDGenerator.cxx b/Source/CPack/cmCPackFreeBSDGenerator.cxx index 607d797..162dfc7 100644 --- a/Source/CPack/cmCPackFreeBSDGenerator.cxx +++ b/Source/CPack/cmCPackFreeBSDGenerator.cxx @@ -23,8 +23,6 @@ // Suffix used to tell libpkg what compression to use static const char FreeBSDPackageCompression[] = "txz"; -// Resulting package file-suffix, for < 1.17 and >= 1.17 versions of libpkg -static const char FreeBSDPackageSuffix_10[] = ".txz"; static const char FreeBSDPackageSuffix_17[] = ".pkg"; cmCPackFreeBSDGenerator::cmCPackFreeBSDGenerator() @@ -83,6 +81,14 @@ public: { if (!isValid()) return false; + // The API in the FreeBSD sources (the header has no documentation), + // is as follows: + // + // int pkg_create(struct pkg_create *pc, const char *metadata, const char + // *plist, bool hash) + // + // We let the plist be determined from what is installed, and all + // the rest comes from the manifest data. int r = pkg_create(d, manifest.c_str(), nullptr, false); return r == 0; } @@ -402,7 +408,8 @@ int cmCPackFreeBSDGenerator::PackageFiles() return 0; } - std::string output_dir = cmSystemTools::CollapseFullPath("../", toplevel); + const std::string output_dir = + cmSystemTools::CollapseFullPath("../", toplevel); PkgCreate package(output_dir, toplevel, manifestname); if (package.isValid()) { if (!package.Create()) { @@ -416,40 +423,33 @@ int cmCPackFreeBSDGenerator::PackageFiles() return 0; } - // Specifically looking for packages suffixed with the TAG, either extension - std::string broken_suffix_10 = - cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), FreeBSDPackageSuffix_10); + // Specifically looking for packages suffixed with the TAG std::string broken_suffix_17 = cmStrCat('-', var_lookup("CPACK_TOPLEVEL_TAG"), FreeBSDPackageSuffix_17); for (std::string& name : packageFileNames) { cmCPackLogger(cmCPackLog::LOG_DEBUG, "Packagefile " << name << std::endl); - if (cmHasSuffix(name, broken_suffix_10)) { - name.replace(name.size() - broken_suffix_10.size(), std::string::npos, - FreeBSDPackageSuffix_10); - break; - } if (cmHasSuffix(name, broken_suffix_17)) { name.replace(name.size() - broken_suffix_17.size(), std::string::npos, FreeBSDPackageSuffix_17); break; } } - // If the name uses a *new* style name, which doesn't exist, but there - // is an *old* style name, then use that instead. This indicates we used - // an older libpkg, which still creates .txz instead of .pkg files. - for (std::string& name : packageFileNames) { - if (cmHasSuffix(name, FreeBSDPackageSuffix_17) && - !cmSystemTools::FileExists(name)) { - const std::string badSuffix(FreeBSDPackageSuffix_17); - const std::string goodSuffix(FreeBSDPackageSuffix_10); - std::string repairedName(name); - repairedName.replace(repairedName.size() - badSuffix.size(), - std::string::npos, goodSuffix); - if (cmSystemTools::FileExists(repairedName)) { - name = repairedName; - cmCPackLogger(cmCPackLog::LOG_DEBUG, - "Repaired packagefile " << name << std::endl); - } + + const std::string packageFileName = + var_lookup("CPACK_PACKAGE_FILE_NAME") + FreeBSDPackageSuffix_17; + if (packageFileNames.size() == 1 && !packageFileName.empty() && + packageFileNames[0] != packageFileName) { + // Since libpkg always writes <name>-<version>.<suffix>, + // if there is a CPACK_PACKAGE_FILE_NAME set, we need to + // rename, and then re-set the name. + const std::string sourceFile = packageFileNames[0]; + const std::string packageSubDirectory = + cmSystemTools::GetParentDirectory(sourceFile); + const std::string targetFileName = + packageSubDirectory + '/' + packageFileName; + if (cmSystemTools::RenameFile(sourceFile, targetFileName)) { + this->packageFileNames.clear(); + this->packageFileNames.emplace_back(targetFileName); } } diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx index 725ea8a..efb94b9 100644 --- a/Source/CPack/cmCPackGeneratorFactory.cxx +++ b/Source/CPack/cmCPackGeneratorFactory.cxx @@ -6,7 +6,7 @@ #include <utility> #include "IFW/cmCPackIFWGenerator.h" -#ifdef HAVE_FREEBSD_PKG +#if ENABLE_BUILD_FREEBSD_PKG # include "cmCPackFreeBSDGenerator.h" #endif #include "cmCPackArchiveGenerator.h" @@ -34,7 +34,7 @@ # include "cmCPackRPMGenerator.h" #endif -#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID)) +#if ENABLE_BUILD_WIX_GENERATOR # include "WiX/cmCPackWIXGenerator.h" #endif @@ -80,7 +80,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() cmCPackCygwinSourceGenerator::CreateGenerator); } #endif -#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID)) +#if ENABLE_BUILD_WIX_GENERATOR if (cmCPackWIXGenerator::CanGenerate()) { this->RegisterGenerator("WIX", "MSI file format via WiX tools", cmCPackWIXGenerator::CreateGenerator); @@ -119,7 +119,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory() cmCPackRPMGenerator::CreateGenerator); } #endif -#ifdef HAVE_FREEBSD_PKG +#if ENABLE_BUILD_FREEBSD_PKG if (cmCPackFreeBSDGenerator::CanGenerate()) { this->RegisterGenerator("FREEBSD", "FreeBSD pkg(8) packages", cmCPackFreeBSDGenerator::CreateGenerator); diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h index f3e25a6..52c1b5c 100644 --- a/Source/CPack/cmCPackGeneratorFactory.h +++ b/Source/CPack/cmCPackGeneratorFactory.h @@ -8,6 +8,8 @@ #include <memory> #include <string> +#include "cmCPackConfigure.h" // IWYU pragma: keep + class cmCPackGenerator; class cmCPackLog; diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx index 217f716..6ca5783 100644 --- a/Source/CPack/cmCPackNSISGenerator.cxx +++ b/Source/CPack/cmCPackNSISGenerator.cxx @@ -242,6 +242,33 @@ int cmCPackNSISGenerator::PackageFiles() this->SetOptionIfNotSet("CPACK_NSIS_LICENSE_PAGE", licenceCode); } + std::string nsisPreArguments; + if (cmValue nsisArguments = + this->GetOption("CPACK_NSIS_EXECUTABLE_PRE_ARGUMENTS")) { + std::vector<std::string> expandedArguments; + cmExpandList(nsisArguments, expandedArguments); + + for (auto& arg : expandedArguments) { + if (!cmHasPrefix(arg, NSIS_OPT)) { + nsisPreArguments = cmStrCat(nsisPreArguments, NSIS_OPT); + } + nsisPreArguments = cmStrCat(nsisPreArguments, arg, ' '); + } + } + + std::string nsisPostArguments; + if (cmValue nsisArguments = + this->GetOption("CPACK_NSIS_EXECUTABLE_POST_ARGUMENTS")) { + std::vector<std::string> expandedArguments; + cmExpandList(nsisArguments, expandedArguments); + for (auto& arg : expandedArguments) { + if (!cmHasPrefix(arg, NSIS_OPT)) { + nsisPostArguments = cmStrCat(nsisPostArguments, NSIS_OPT); + } + nsisPostArguments = cmStrCat(nsisPostArguments, arg, ' '); + } + } + // Setup all of the component sections if (this->Components.empty()) { this->SetOptionIfNotSet("CPACK_NSIS_INSTALLATION_TYPES", ""); @@ -358,8 +385,11 @@ int cmCPackNSISGenerator::PackageFiles() this->ConfigureFile(nsisInInstallOptions, nsisInstallOptions); this->ConfigureFile(nsisInFileName, nsisFileName); std::string nsisCmd = - cmStrCat('"', this->GetOption("CPACK_INSTALLER_PROGRAM"), "\" \"", - nsisFileName, '"'); + cmStrCat('"', this->GetOption("CPACK_INSTALLER_PROGRAM"), "\" ", + nsisPreArguments, " \"", nsisFileName, '"'); + if (!nsisPostArguments.empty()) { + nsisCmd = cmStrCat(nsisCmd, " ", nsisPostArguments); + } cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd << std::endl); std::string output; int retVal = 1; diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 221f7dd..631bfd9 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -1,6 +1,7 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ +#include <algorithm> #include <cstddef> #include <functional> #include <iostream> @@ -11,10 +12,12 @@ #include <utility> #include <vector> +#include <cm/optional> #include <cmext/algorithm> #include "cmsys/Encoding.hxx" +#include "cmCMakePresetsGraph.h" #include "cmCPackGenerator.h" #include "cmCPackGeneratorFactory.h" #include "cmCPackLog.h" @@ -50,7 +53,7 @@ const char* cmDocumentationOptions[][2] = { { "-C <Configuration>", "Specify the project configuration" }, { "-D <var>=<value>", "Set a CPack variable." }, { "--config <configFile>", "Specify the config file." }, - { "--verbose,-V", "Enable verbose output" }, + { "-V,--verbose", "Enable verbose output" }, { "--trace", "Put underlying cmake scripts in trace mode." }, { "--trace-expand", "Put underlying cmake scripts in expanded trace mode." }, { "--debug", "Enable debug output (for CPack developers)" }, @@ -58,6 +61,8 @@ const char* cmDocumentationOptions[][2] = { { "-R <packageVersion>", "Override/define CPACK_PACKAGE_VERSION" }, { "-B <packageDirectory>", "Override/define CPACK_PACKAGE_DIRECTORY" }, { "--vendor <vendorName>", "Override/define CPACK_PACKAGE_VENDOR" }, + { "--preset", "Read arguments from a package preset" }, + { "--list-presets", "List available package presets" }, { nullptr, nullptr } }; @@ -116,6 +121,9 @@ int main(int argc, char const* const* argv) std::string cpackProjectVendor; std::string cpackConfigFile; + std::string preset; + bool listPresets = false; + std::map<std::string, std::string> definitions; auto const verboseLambda = [&log](const std::string&, cmake*, @@ -182,6 +190,10 @@ int main(int argc, char const* const* argv) CommandArgument::setToValue(cpackProjectPatch) }, CommandArgument{ "--vendor", CommandArgument::Values::One, CommandArgument::setToValue(cpackProjectVendor) }, + CommandArgument{ "--preset", CommandArgument::Values::One, + CommandArgument::setToValue(preset) }, + CommandArgument{ "--list-presets", CommandArgument::Values::Zero, + CommandArgument::setToTrue(listPresets) }, CommandArgument{ "-D", CommandArgument::Values::One, [&log, &definitions](const std::string& arg, cmake*, @@ -228,6 +240,160 @@ int main(int argc, char const* const* argv) } } + cmCPackGeneratorFactory generators; + generators.SetLogger(&log); + + // Set up presets + if (!preset.empty() || listPresets) { + const auto workingDirectory = cmSystemTools::GetCurrentWorkingDirectory(); + + auto const presetGeneratorsPresent = + [&generators](const cmCMakePresetsGraph::PackagePreset& p) { + return std::all_of(p.Generators.begin(), p.Generators.end(), + [&generators](const std::string& gen) { + return generators.GetGeneratorsList().count( + gen) != 0; + }); + }; + + cmCMakePresetsGraph presetsGraph; + auto result = presetsGraph.ReadProjectPresets(workingDirectory); + if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, + "Could not read presets from " + << workingDirectory << ": " + << cmCMakePresetsGraph::ResultToString(result) + << std::endl); + return 1; + } + + if (listPresets) { + presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); + return 0; + } + + auto presetPair = presetsGraph.PackagePresets.find(preset); + if (presetPair == presetsGraph.PackagePresets.end()) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, + "No such package preset in " << workingDirectory << ": \"" + << preset << '"' << std::endl); + presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); + return 1; + } + + if (presetPair->second.Unexpanded.Hidden) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, + "Cannot use hidden package preset in " + << workingDirectory << ": \"" << preset << '"' + << std::endl); + presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); + return 1; + } + + auto const& expandedPreset = presetPair->second.Expanded; + if (!expandedPreset) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, + "Could not evaluate package preset \"" + << preset << "\": Invalid macro expansion" << std::endl); + presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); + return 1; + } + + if (!expandedPreset->ConditionResult) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, + "Cannot use disabled package preset in " + << workingDirectory << ": \"" << preset << '"' + << std::endl); + presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); + return 1; + } + + if (!presetGeneratorsPresent(presetPair->second.Unexpanded)) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, "Cannot use preset"); + presetsGraph.PrintPackagePresetList(presetGeneratorsPresent); + return 1; + } + + auto configurePresetPair = + presetsGraph.ConfigurePresets.find(expandedPreset->ConfigurePreset); + if (configurePresetPair == presetsGraph.ConfigurePresets.end()) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, + "No such configure preset in " + << workingDirectory << ": \"" + << expandedPreset->ConfigurePreset << '"' << std::endl); + presetsGraph.PrintConfigurePresetList(); + return 1; + } + + if (configurePresetPair->second.Unexpanded.Hidden) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, + "Cannot use hidden configure preset in " + << workingDirectory << ": \"" + << expandedPreset->ConfigurePreset << '"' << std::endl); + presetsGraph.PrintConfigurePresetList(); + return 1; + } + + auto const& expandedConfigurePreset = configurePresetPair->second.Expanded; + if (!expandedConfigurePreset) { + cmCPack_Log(&log, cmCPackLog::LOG_ERROR, + "Could not evaluate configure preset \"" + << expandedPreset->ConfigurePreset + << "\": Invalid macro expansion" << std::endl); + return 1; + } + + cmSystemTools::ChangeDirectory(expandedConfigurePreset->BinaryDir); + + auto presetEnvironment = expandedPreset->Environment; + for (auto const& var : presetEnvironment) { + if (var.second) { + cmSystemTools::PutEnv(cmStrCat(var.first, '=', *var.second)); + } + } + + if (!expandedPreset->ConfigFile.empty() && cpackConfigFile.empty()) { + cpackConfigFile = expandedPreset->ConfigFile; + } + + if (!expandedPreset->Generators.empty() && generator.empty()) { + generator = cmJoin(expandedPreset->Generators, ";"); + } + + if (!expandedPreset->Configurations.empty() && cpackBuildConfig.empty()) { + cpackBuildConfig = cmJoin(expandedPreset->Configurations, ";"); + } + + definitions.insert(expandedPreset->Variables.begin(), + expandedPreset->Variables.end()); + + if (expandedPreset->DebugOutput == true) { + debugLambda("", &cminst, &globalMF); + } + + if (expandedPreset->VerboseOutput == true) { + verboseLambda("", &cminst, &globalMF); + } + + if (!expandedPreset->PackageName.empty() && cpackProjectName.empty()) { + cpackProjectName = expandedPreset->PackageName; + } + + if (!expandedPreset->PackageVersion.empty() && + cpackProjectVersion.empty()) { + cpackProjectVersion = expandedPreset->PackageVersion; + } + + if (!expandedPreset->PackageDirectory.empty() && + cpackProjectDirectory.empty()) { + cpackProjectDirectory = expandedPreset->PackageDirectory; + } + + if (!expandedPreset->VendorName.empty() && cpackProjectVendor.empty()) { + cpackProjectVendor = expandedPreset->VendorName; + } + } + cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE, "Read CPack config file: " << cpackConfigFile << std::endl); @@ -238,9 +404,6 @@ int main(int argc, char const* const* argv) cpackConfigFileSpecified = false; } - cmCPackGeneratorFactory generators; - generators.SetLogger(&log); - cmDocumentation doc; doc.addCPackStandardDocSections(); /* Were we invoked to display doc or to do some work ? diff --git a/Source/CTest/cmCTestCoverageCommand.cxx b/Source/CTest/cmCTestCoverageCommand.cxx index 7432d08..97b0a89 100644 --- a/Source/CTest/cmCTestCoverageCommand.cxx +++ b/Source/CTest/cmCTestCoverageCommand.cxx @@ -4,7 +4,6 @@ #include <set> -#include <cmext/algorithm> #include <cmext/string_view> #include "cmCTest.h" @@ -18,13 +17,6 @@ void cmCTestCoverageCommand::BindArguments() this->Bind("LABELS"_s, this->Labels); } -void cmCTestCoverageCommand::CheckArguments( - std::vector<std::string> const& keywords) -{ - this->LabelsMentioned = - !this->Labels.empty() || cm::contains(keywords, "LABELS"); -} - cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler() { this->CTest->SetCTestConfigurationFromCMakeVariable( @@ -36,9 +28,9 @@ cmCTestGenericHandler* cmCTestCoverageCommand::InitializeHandler() handler->Initialize(); // If a LABELS option was given, select only files with the labels. - if (this->LabelsMentioned) { + if (this->Labels) { handler->SetLabelFilter( - std::set<std::string>(this->Labels.begin(), this->Labels.end())); + std::set<std::string>(this->Labels->begin(), this->Labels->end())); } handler->SetQuiet(this->Quiet); diff --git a/Source/CTest/cmCTestCoverageCommand.h b/Source/CTest/cmCTestCoverageCommand.h index 9344852..55c68b2 100644 --- a/Source/CTest/cmCTestCoverageCommand.h +++ b/Source/CTest/cmCTestCoverageCommand.h @@ -9,7 +9,9 @@ #include <vector> #include <cm/memory> +#include <cm/optional> +#include "cmArgumentParserTypes.h" // IWYU pragma: keep #include "cmCTestHandlerCommand.h" #include "cmCommand.h" @@ -41,9 +43,7 @@ public: protected: void BindArguments() override; - void CheckArguments(std::vector<std::string> const& keywords) override; cmCTestGenericHandler* InitializeHandler() override; - bool LabelsMentioned; - std::vector<std::string> Labels; + cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Labels; }; diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 5494d20..be952cd 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -7,6 +7,7 @@ #include <cstring> #include <sstream> +#include <cm/string_view> #include <cmext/string_view> #include "cmCTest.h" @@ -81,15 +82,13 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, // Process input arguments. std::vector<std::string> unparsedArguments; - std::vector<std::string> keywordsMissingValue; - std::vector<std::string> parsedKeywords; - this->Parse(args, &unparsedArguments, &keywordsMissingValue, - &parsedKeywords); - this->CheckArguments(keywordsMissingValue); - - std::sort(parsedKeywords.begin(), parsedKeywords.end()); - auto it = std::adjacent_find(parsedKeywords.begin(), parsedKeywords.end()); - if (it != parsedKeywords.end()) { + this->Parse(args, &unparsedArguments); + this->CheckArguments(); + + std::sort(this->ParsedKeywords.begin(), this->ParsedKeywords.end()); + auto it = std::adjacent_find(this->ParsedKeywords.begin(), + this->ParsedKeywords.end()); + if (it != this->ParsedKeywords.end()) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, cmStrCat("Called with more than one value for ", *it)); @@ -233,6 +232,7 @@ void cmCTestHandlerCommand::ProcessAdditionalValues(cmCTestGenericHandler*) void cmCTestHandlerCommand::BindArguments() { + this->BindParsedKeywords(this->ParsedKeywords); this->Bind("APPEND"_s, this->Append); this->Bind("QUIET"_s, this->Quiet); this->Bind("RETURN_VALUE"_s, this->ReturnValue); @@ -242,6 +242,6 @@ void cmCTestHandlerCommand::BindArguments() this->Bind("SUBMIT_INDEX"_s, this->SubmitIndex); } -void cmCTestHandlerCommand::CheckArguments(std::vector<std::string> const&) +void cmCTestHandlerCommand::CheckArguments() { } diff --git a/Source/CTest/cmCTestHandlerCommand.h b/Source/CTest/cmCTestHandlerCommand.h index 756952d..ed6d9af 100644 --- a/Source/CTest/cmCTestHandlerCommand.h +++ b/Source/CTest/cmCTestHandlerCommand.h @@ -7,6 +7,8 @@ #include <string> #include <vector> +#include <cm/string_view> + #include "cmArgumentParser.h" #include "cmCTestCommand.h" @@ -42,8 +44,9 @@ protected: // Command argument handling. virtual void BindArguments(); - virtual void CheckArguments(std::vector<std::string> const& keywords); + virtual void CheckArguments(); + std::vector<cm::string_view> ParsedKeywords; bool Append = false; bool Quiet = false; std::string CaptureCMakeError; diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 788845b..6f6a642 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -1177,6 +1177,13 @@ bool cmCTestMemCheckHandler::ProcessMemCheckCudaOutput( // generic error: ignore ERROR SUMMARY, CUDA-MEMCHECK and others "== ([A-Z][a-z].*)" }; + // matchers for messages that aren't defects, but caught by above matchers + std::vector<cmsys::RegularExpression> false_positive_matchers{ + "== Error: No attachable process found.*timed-out", + "== Default timeout can be adjusted with --launch-timeout", + "== Error: Target application terminated before first instrumented API", + "== Tracking kernels launched by child processes requires" + }; std::vector<std::string::size_type> nonMemcheckOutput; auto sttime = std::chrono::steady_clock::now(); @@ -1196,11 +1203,17 @@ bool cmCTestMemCheckHandler::ProcessMemCheckCudaOutput( if (leakExpr.find(line)) { failure = static_cast<int>(this->FindOrAddWarning("Memory leak")); } else { - for (auto& matcher : matchers) { - if (matcher.find(line)) { + auto match_predicate = + [&line](cmsys::RegularExpression& matcher) -> bool { + return matcher.find(line); + }; + auto const pos_matcher = + std::find_if(matchers.begin(), matchers.end(), match_predicate); + if (pos_matcher != matchers.end()) { + if (!std::any_of(false_positive_matchers.begin(), + false_positive_matchers.end(), match_predicate)) { failure = - static_cast<int>(this->FindOrAddWarning(matcher.match(1))); - break; + static_cast<int>(this->FindOrAddWarning(pos_matcher->match(1))); } } } diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 2a2cb1c..5efe69f 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -8,16 +8,12 @@ #include <cstdint> #include <cstdio> #include <cstring> -#include <functional> #include <iomanip> #include <ratio> #include <sstream> #include <utility> #include <cm/memory> -#include <cm/optional> -#include <cm/string_view> -#include <cmext/string_view> #include "cmsys/RegularExpression.hxx" @@ -787,149 +783,31 @@ bool cmCTestRunTest::ForkProcess( this->TestProcess->SetTimeout(timeout); -#ifndef CMAKE_BOOTSTRAP cmSystemTools::SaveRestoreEnvironment sre; -#endif - std::ostringstream envMeasurement; + + // We split processing ENVIRONMENT and ENVIRONMENT_MODIFICATION into two + // phases to ensure that MYVAR=reset: in the latter phase resets to the + // former phase's settings, rather than to the original environment. if (environment && !environment->empty()) { - // Environment modification works on the assumption that the environment is - // actually modified here. If another strategy is used, there will need to - // be updates below in `apply_diff`. - cmSystemTools::AppendEnv(*environment); - for (auto const& var : *environment) { - envMeasurement << var << std::endl; - } + cmSystemTools::EnvDiff diff; + diff.AppendEnv(*environment); + diff.ApplyToCurrentEnv(&envMeasurement); } if (environment_modification && !environment_modification->empty()) { - std::map<std::string, cm::optional<std::string>> env_application; - -#ifdef _WIN32 - char path_sep = ';'; -#else - char path_sep = ':'; -#endif - - auto apply_diff = - [&env_application](const std::string& name, - std::function<void(std::string&)> const& apply) { - cm::optional<std::string> old_value = env_application[name]; - std::string output; - if (old_value) { - output = *old_value; - } else { - // This only works because the environment is actually modified above - // (`AppendEnv`). If CTest ever just creates an environment block - // directly, that block will need to be queried for the subprocess' - // value instead. - const char* curval = cmSystemTools::GetEnv(name); - if (curval) { - output = curval; - } - } - apply(output); - env_application[name] = output; - }; - - bool err_occurred = false; + cmSystemTools::EnvDiff diff; + bool env_ok = true; for (auto const& envmod : *environment_modification) { - // Split on `=` - auto const eq_loc = envmod.find_first_of('='); - if (eq_loc == std::string::npos) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Error: Missing `=` after the variable name in: " - << envmod << std::endl); - err_occurred = true; - continue; - } - auto const name = envmod.substr(0, eq_loc); - - // Split value on `:` - auto const op_value_start = eq_loc + 1; - auto const colon_loc = envmod.find_first_of(':', op_value_start); - if (colon_loc == std::string::npos) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Error: Missing `:` after the operation in: " << envmod - << std::endl); - err_occurred = true; - continue; - } - auto const op = - envmod.substr(op_value_start, colon_loc - op_value_start); - - auto const value_start = colon_loc + 1; - auto const value = envmod.substr(value_start); - - // Determine what to do with the operation. - if (op == "reset"_s) { - auto entry = env_application.find(name); - if (entry != env_application.end()) { - env_application.erase(entry); - } - } else if (op == "set"_s) { - env_application[name] = value; - } else if (op == "unset"_s) { - env_application[name] = {}; - } else if (op == "string_append"_s) { - apply_diff(name, [&value](std::string& output) { output += value; }); - } else if (op == "string_prepend"_s) { - apply_diff(name, - [&value](std::string& output) { output.insert(0, value); }); - } else if (op == "path_list_append"_s) { - apply_diff(name, [&value, path_sep](std::string& output) { - if (!output.empty()) { - output += path_sep; - } - output += value; - }); - } else if (op == "path_list_prepend"_s) { - apply_diff(name, [&value, path_sep](std::string& output) { - if (!output.empty()) { - output.insert(output.begin(), path_sep); - } - output.insert(0, value); - }); - } else if (op == "cmake_list_append"_s) { - apply_diff(name, [&value](std::string& output) { - if (!output.empty()) { - output += ';'; - } - output += value; - }); - } else if (op == "cmake_list_prepend"_s) { - apply_diff(name, [&value](std::string& output) { - if (!output.empty()) { - output.insert(output.begin(), ';'); - } - output.insert(0, value); - }); - } else { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "Error: Unrecognized environment manipulation argument: " - << op << std::endl); - err_occurred = true; - continue; - } + env_ok &= diff.ParseOperation(envmod); } - if (err_occurred) { + if (!env_ok) { return false; } - for (auto const& env_apply : env_application) { - if (env_apply.second) { - auto const env_update = - cmStrCat(env_apply.first, '=', *env_apply.second); - cmSystemTools::PutEnv(env_update); - envMeasurement << env_update << std::endl; - } else { - cmSystemTools::UnsetEnv(env_apply.first.c_str()); - // Signify that this variable is being actively unset - envMeasurement << "#" << env_apply.first << "=" << std::endl; - } - } + diff.ApplyToCurrentEnv(&envMeasurement); } if (this->UseAllocatedResources) { diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx index a2dc615..a1933cc 100644 --- a/Source/CTest/cmCTestSubmitCommand.cxx +++ b/Source/CTest/cmCTestSubmitCommand.cxx @@ -8,7 +8,6 @@ #include <cm/memory> #include <cm/vector> -#include <cmext/algorithm> #include <cmext/string_view> #include "cmCTest.h" @@ -87,7 +86,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() // If FILES are given, but not PARTS, only the FILES are submitted // and *no* PARTS are submitted. // (This is why we select the empty "noParts" set in the - // FilesMentioned block below...) + // if(this->Files) block below...) // // If PARTS are given, only the selected PARTS are submitted. // @@ -96,7 +95,7 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() // If given explicit FILES to submit, pass them to the handler. // - if (this->FilesMentioned) { + if (this->Files) { // Intentionally select *no* PARTS. (Pass an empty set.) If PARTS // were also explicitly mentioned, they will be selected below... // But FILES with no PARTS mentioned should just submit the FILES @@ -104,14 +103,14 @@ cmCTestGenericHandler* cmCTestSubmitCommand::InitializeHandler() // handler->SelectParts(std::set<cmCTest::Part>()); handler->SelectFiles( - std::set<std::string>(this->Files.begin(), this->Files.end())); + std::set<std::string>(this->Files->begin(), this->Files->end())); } // If a PARTS option was given, select only the named parts for submission. // - if (this->PartsMentioned) { + if (this->Parts) { auto parts = - cmMakeRange(this->Parts).transform([this](std::string const& arg) { + cmMakeRange(*(this->Parts)).transform([this](std::string const& arg) { return this->CTest->GetPartFromName(arg); }); handler->SelectParts(std::set<cmCTest::Part>(parts.begin(), parts.end())); @@ -172,33 +171,31 @@ void cmCTestSubmitCommand::BindArguments() this->cmCTestHandlerCommand::BindArguments(); } -void cmCTestSubmitCommand::CheckArguments( - std::vector<std::string> const& keywords) +void cmCTestSubmitCommand::CheckArguments() { - this->PartsMentioned = - !this->Parts.empty() || cm::contains(keywords, "PARTS"); - this->FilesMentioned = - !this->Files.empty() || cm::contains(keywords, "FILES"); - - cm::erase_if(this->Parts, [this](std::string const& arg) -> bool { - cmCTest::Part p = this->CTest->GetPartFromName(arg); - if (p == cmCTest::PartCount) { - std::ostringstream e; - e << "Part name \"" << arg << "\" is invalid."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); - return true; - } - return false; - }); - - cm::erase_if(this->Files, [this](std::string const& arg) -> bool { - if (!cmSystemTools::FileExists(arg)) { - std::ostringstream e; - e << "File \"" << arg << "\" does not exist. Cannot submit " - << "a non-existent file."; - this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); - return true; - } - return false; - }); + if (this->Parts) { + cm::erase_if(*(this->Parts), [this](std::string const& arg) -> bool { + cmCTest::Part p = this->CTest->GetPartFromName(arg); + if (p == cmCTest::PartCount) { + std::ostringstream e; + e << "Part name \"" << arg << "\" is invalid."; + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return true; + } + return false; + }); + } + + if (this->Files) { + cm::erase_if(*(this->Files), [this](std::string const& arg) -> bool { + if (!cmSystemTools::FileExists(arg)) { + std::ostringstream e; + e << "File \"" << arg << "\" does not exist. Cannot submit " + << "a non-existent file."; + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return true; + } + return false; + }); + } } diff --git a/Source/CTest/cmCTestSubmitCommand.h b/Source/CTest/cmCTestSubmitCommand.h index c5d11df..b67f182 100644 --- a/Source/CTest/cmCTestSubmitCommand.h +++ b/Source/CTest/cmCTestSubmitCommand.h @@ -8,6 +8,9 @@ #include <string> #include <vector> +#include <cm/optional> + +#include "cmArgumentParserTypes.h" #include "cmCTestHandlerCommand.h" class cmCommand; @@ -35,13 +38,11 @@ public: protected: void BindArguments() override; - void CheckArguments(std::vector<std::string> const& keywords) override; + void CheckArguments() override; cmCTestGenericHandler* InitializeHandler() override; bool CDashUpload = false; - bool FilesMentioned = false; bool InternalTest = false; - bool PartsMentioned = false; std::string BuildID; std::string CDashUploadFile; @@ -50,7 +51,7 @@ protected: std::string RetryDelay; std::string SubmitURL; - std::vector<std::string> Files; - std::vector<std::string> HttpHeaders; - std::vector<std::string> Parts; + cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Files; + ArgumentParser::MaybeEmpty<std::vector<std::string>> HttpHeaders; + cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Parts; }; diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx index f86ee0d..2ed671c 100644 --- a/Source/CTest/cmCTestUploadCommand.cxx +++ b/Source/CTest/cmCTestUploadCommand.cxx @@ -21,7 +21,7 @@ void cmCTestUploadCommand::BindArguments() this->Bind("CAPTURE_CMAKE_ERROR"_s, this->CaptureCMakeError); } -void cmCTestUploadCommand::CheckArguments(std::vector<std::string> const&) +void cmCTestUploadCommand::CheckArguments() { cm::erase_if(this->Files, [this](std::string const& arg) -> bool { if (!cmSystemTools::FileExists(arg)) { diff --git a/Source/CTest/cmCTestUploadCommand.h b/Source/CTest/cmCTestUploadCommand.h index fe155f6..a9d1dd2 100644 --- a/Source/CTest/cmCTestUploadCommand.h +++ b/Source/CTest/cmCTestUploadCommand.h @@ -10,6 +10,7 @@ #include <cm/memory> +#include "cmArgumentParserTypes.h" #include "cmCTestHandlerCommand.h" #include "cmCommand.h" @@ -42,8 +43,8 @@ public: protected: void BindArguments() override; - void CheckArguments(std::vector<std::string> const&) override; + void CheckArguments() override; cmCTestGenericHandler* InitializeHandler() override; - std::vector<std::string> Files; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Files; }; diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index b14a751..6e6f0d6 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -85,7 +85,7 @@ void cmCursesLongMessageForm::UpdateStatusBar() for (size_t i = 0; i < sideSpace; i++) { version[i] = ' '; } - sprintf(version + sideSpace, "%s", vertmp); + snprintf(version + sideSpace, sizeof(version) - sideSpace, "%s", vertmp); version[width] = '\0'; char fmt_s[] = "%s"; diff --git a/Source/CursesDialog/form/.gitattributes b/Source/CursesDialog/form/.gitattributes index 12ede74..6dfa627 100644 --- a/Source/CursesDialog/form/.gitattributes +++ b/Source/CursesDialog/form/.gitattributes @@ -1 +1,2 @@ +* -whitespace * -format.clang-format-6.0 diff --git a/Source/CursesDialog/form/CMakeLists.txt b/Source/CursesDialog/form/CMakeLists.txt index 68d28c8..63214e3 100644 --- a/Source/CursesDialog/form/CMakeLists.txt +++ b/Source/CursesDialog/form/CMakeLists.txt @@ -11,7 +11,7 @@ elseif(CMAKE_C_COMPILER_ID STREQUAL "PathScale") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -woffall") endif() -configure_file(cmFormConfigure.h.in "${CMAKE_CURRENT_BINARY_DIR}/cmFormConfigure.h") +configure_file(cmFormConfigure.h.in cmFormConfigure.h) add_library(cmForm fld_arg.c diff --git a/Source/CursesDialog/form/fty_int.c b/Source/CursesDialog/form/fty_int.c index 7107fcc..7aeb4b8 100644 --- a/Source/CursesDialog/form/fty_int.c +++ b/Source/CursesDialog/form/fty_int.c @@ -117,7 +117,7 @@ static bool Check_Integer_Field(FIELD * field, const void * argp) { if (val<low || val>high) return FALSE; } - sprintf(buf,"%.*ld",(prec>0?prec:0),val); + snprintf(buf,sizeof(buf),"%.*ld",(prec>0?prec:0),val); set_field_buffer(field,0,buf); return TRUE; } diff --git a/Source/CursesDialog/form/fty_num.c b/Source/CursesDialog/form/fty_num.c index 7809599..4109b6f 100644 --- a/Source/CursesDialog/form/fty_num.c +++ b/Source/CursesDialog/form/fty_num.c @@ -140,7 +140,7 @@ static bool Check_Numeric_Field(FIELD * field, const void * argp) { if (val<low || val>high) return FALSE; } - sprintf(buf,"%.*f",(prec>0?prec:0),val); + snprintf(buf,sizeof(buf),"%.*f",(prec>0?prec:0),val); set_field_buffer(field,0,buf); return TRUE; } diff --git a/Source/LexerParser/cmFortranLexer.cxx b/Source/LexerParser/cmFortranLexer.cxx index c3d0000..5703de1 100644 --- a/Source/LexerParser/cmFortranLexer.cxx +++ b/Source/LexerParser/cmFortranLexer.cxx @@ -557,31 +557,32 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[210] = +static const flex_int16_t yy_accept[216] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 49, 51, 50, 53, 1, 49, 33, 2, 47, 48, 35, 37, 50, 39, 49, 46, 46, 46, 46, - 46, 46, 49, 46, 51, 49, 50, 49, 46, 9, - 8, 9, 4, 3, 49, 0, 10, 0, 0, 0, - 0, 0, 33, 33, 34, 36, 39, 49, 46, 46, - 46, 46, 46, 46, 0, 52, 46, 0, 0, 0, - 12, 0, 0, 0, 0, 0, 0, 49, 0, 11, - 46, 0, 0, 5, 0, 0, 0, 0, 29, 0, - 33, 33, 33, 33, 0, 0, 40, 46, 46, 46, - - 46, 45, 12, 12, 0, 0, 0, 23, 0, 0, - 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 46, 46, 46, 46, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 30, 31, 0, 0, 0, 0, 0, 46, 46, - 46, 46, 0, 24, 25, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 20, 32, 27, 0, 0, 0, - 46, 46, 43, 46, 0, 26, 21, 0, 0, 0, - 19, 0, 0, 18, 28, 0, 0, 41, 46, 46, - 17, 22, 0, 7, 38, 7, 15, 0, 46, 46, - - 14, 16, 42, 44, 0, 0, 0, 13, 0 + 46, 46, 49, 46, 51, 49, 50, 51, 49, 46, + 9, 8, 9, 9, 4, 3, 49, 0, 10, 0, + 0, 0, 0, 0, 33, 33, 34, 36, 39, 49, + 46, 46, 46, 46, 46, 46, 0, 52, 0, 46, + 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, + 0, 49, 0, 11, 46, 0, 0, 0, 5, 0, + 0, 0, 0, 0, 29, 0, 33, 33, 33, 33, + + 0, 0, 40, 46, 46, 46, 46, 45, 12, 12, + 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 46, 46, 46, 46, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 30, 31, 0, + 0, 0, 0, 0, 46, 46, 46, 46, 0, 24, + 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 20, 32, 27, 0, 0, 0, 46, 46, 43, 46, + 0, 26, 21, 0, 0, 0, 19, 0, 0, 18, + 28, 0, 0, 41, 46, 46, 17, 22, 0, 7, + + 38, 7, 15, 0, 46, 46, 14, 16, 42, 44, + 0, 0, 0, 13, 0 } ; static const YY_CHAR yy_ec[256] = @@ -618,189 +619,197 @@ static const YY_CHAR yy_ec[256] = static const YY_CHAR yy_meta[50] = { 0, - 1, 2, 2, 3, 4, 3, 3, 1, 1, 3, - 3, 3, 3, 1, 3, 5, 3, 3, 1, 3, + 1, 2, 2, 2, 3, 4, 4, 1, 1, 4, + 4, 4, 4, 1, 4, 5, 4, 4, 1, 4, 6, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7 } ; -static const flex_int16_t yy_base[219] = +static const flex_int16_t yy_base[225] = { 0, - 0, 48, 0, 49, 464, 56, 52, 57, 62, 68, - 466, 0, 468, 468, 462, 468, 74, 81, 468, 468, - 468, 468, 447, 468, 442, 440, 0, 19, 41, 427, - 47, 41, 90, 119, 97, 158, 455, 207, 247, 468, - 454, 101, 468, 468, 0, 455, 468, 105, 430, 423, - 62, 67, 119, 151, 468, 468, 468, 121, 0, 90, - 93, 110, 431, 112, 142, 468, 0, 160, 295, 0, - 162, 411, 123, 102, 408, 405, 446, 344, 447, 468, - 0, 444, 170, 174, 420, 421, 132, 404, 95, 404, - 180, 186, 192, 228, 297, 397, 0, 168, 144, 52, - - 411, 0, 204, 217, 397, 179, 390, 170, 389, 378, - 364, 390, 389, 230, 468, 363, 355, 337, 337, 334, - 335, 335, 330, 334, 187, 339, 267, 339, 327, 327, - 327, 324, 325, 325, 318, 319, 318, 354, 352, 323, - 327, 468, 468, 310, 307, 305, 297, 297, 275, 275, - 277, 279, 287, 468, 468, 286, 283, 273, 196, 307, - 200, 238, 234, 210, 468, 468, 468, 174, 171, 162, - 279, 182, 0, 269, 150, 468, 468, 137, 109, 323, - 468, 239, 0, 468, 468, 72, 71, 0, 283, 283, - 468, 468, 51, 468, 468, 468, 468, 37, 283, 288, - - 330, 468, 0, 0, 331, 0, 52, 468, 468, 384, - 391, 397, 400, 407, 414, 421, 428, 435 + 0, 48, 0, 49, 55, 58, 64, 66, 75, 83, + 491, 0, 492, 492, 487, 492, 86, 92, 492, 492, + 492, 492, 472, 492, 467, 465, 0, 56, 59, 452, + 66, 16, 105, 131, 109, 170, 480, 481, 219, 259, + 492, 478, 479, 116, 492, 492, 0, 478, 492, 111, + 453, 446, 34, 78, 155, 174, 492, 492, 492, 121, + 0, 29, 105, 101, 454, 101, 131, 492, 474, 0, + 180, 307, 0, 146, 433, 117, 94, 430, 427, 468, + 467, 356, 468, 492, 0, 465, 464, 187, 191, 465, + 439, 440, 149, 423, 126, 423, 200, 240, 311, 322, + + 206, 416, 0, 152, 180, 176, 430, 0, 216, 224, + 417, 186, 418, 127, 418, 411, 415, 451, 450, 247, + 492, 423, 416, 398, 393, 373, 364, 364, 359, 353, + 198, 358, 178, 358, 346, 346, 346, 343, 344, 344, + 338, 340, 339, 376, 374, 343, 346, 492, 492, 329, + 325, 324, 313, 315, 211, 211, 291, 293, 313, 492, + 492, 314, 304, 304, 261, 328, 212, 249, 243, 203, + 492, 492, 492, 173, 158, 150, 293, 172, 0, 273, + 144, 492, 492, 137, 125, 335, 492, 339, 0, 492, + 492, 112, 63, 0, 304, 300, 492, 492, 58, 492, + + 492, 492, 492, 30, 311, 312, 361, 492, 0, 0, + 366, 0, 44, 492, 492, 396, 403, 409, 412, 419, + 426, 433, 440, 447 } ; -static const flex_int16_t yy_def[219] = +static const flex_int16_t yy_def[225] = { 0, - 209, 1, 1, 1, 1, 1, 210, 210, 210, 210, - 209, 211, 209, 209, 212, 209, 211, 209, 209, 209, - 209, 209, 209, 209, 209, 211, 213, 213, 213, 213, - 213, 213, 211, 213, 209, 211, 209, 214, 209, 209, - 209, 209, 209, 209, 211, 212, 209, 209, 209, 209, - 209, 209, 209, 215, 209, 209, 209, 211, 213, 213, - 213, 213, 213, 213, 209, 209, 34, 209, 209, 69, - 211, 209, 209, 209, 209, 209, 209, 214, 214, 209, - 39, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 215, 215, 215, 215, 209, 209, 213, 213, 213, 213, - - 213, 213, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 213, 213, 213, 213, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 213, 213, - 213, 213, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 213, 213, 213, 213, 209, 209, 209, 209, 209, 209, - 209, 216, 217, 209, 209, 209, 209, 213, 213, 213, - 209, 209, 209, 209, 209, 209, 209, 209, 213, 213, - - 209, 209, 213, 213, 209, 218, 218, 209, 0, 209, - 209, 209, 209, 209, 209, 209, 209, 209 + 215, 1, 1, 1, 1, 1, 216, 216, 216, 216, + 215, 217, 215, 215, 218, 215, 217, 215, 215, 215, + 215, 215, 215, 215, 215, 217, 219, 219, 219, 219, + 219, 219, 217, 219, 215, 217, 215, 215, 220, 215, + 215, 215, 215, 215, 215, 215, 217, 218, 215, 215, + 215, 215, 215, 215, 215, 221, 215, 215, 215, 217, + 219, 219, 219, 219, 219, 219, 215, 215, 215, 34, + 215, 215, 72, 217, 215, 215, 215, 215, 215, 215, + 215, 220, 220, 215, 40, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 221, 221, 221, 221, + + 215, 215, 219, 219, 219, 219, 219, 219, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 219, 219, 219, 219, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 219, 219, 219, 219, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 219, 219, 219, 219, + 215, 215, 215, 215, 215, 215, 215, 222, 223, 215, + 215, 215, 215, 219, 219, 219, 215, 215, 215, 215, + + 215, 215, 215, 215, 219, 219, 215, 215, 219, 219, + 215, 224, 224, 215, 0, 215, 215, 215, 215, 215, + 215, 215, 215, 215 } ; -static const flex_int16_t yy_nxt[518] = +static const flex_int16_t yy_nxt[542] = { 0, 12, 13, 14, 13, 13, 15, 16, 12, 17, 18, 19, 20, 21, 12, 22, 12, 23, 24, 12, 25, 12, 26, 27, 27, 27, 27, 28, 27, 27, 29, 27, 30, 27, 27, 27, 31, 27, 32, 33, 34, 27, 27, 28, 27, 29, 27, 27, 31, 32, 35, - 35, 60, 35, 35, 41, 36, 36, 35, 37, 41, - 35, 42, 43, 36, 41, 60, 42, 43, 44, 38, - 41, 42, 208, 61, 44, 48, 64, 42, 48, 202, - 39, 39, 53, 53, 63, 53, 54, 61, 64, 127, - 55, 65, 66, 201, 65, 63, 39, 39, 68, 49, - - 127, 68, 83, 84, 69, 83, 48, 87, 88, 48, - 89, 50, 198, 90, 197, 97, 51, 98, 52, 45, - 53, 53, 95, 53, 54, 95, 45, 45, 55, 99, - 49, 97, 45, 98, 67, 100, 121, 45, 102, 45, - 45, 122, 50, 65, 66, 108, 65, 51, 109, 52, - 193, 100, 92, 53, 102, 92, 93, 45, 67, 70, - 94, 68, 70, 104, 68, 96, 104, 69, 106, 107, - 126, 83, 84, 71, 83, 114, 118, 71, 114, 119, - 192, 92, 53, 115, 92, 93, 126, 92, 53, 94, - 92, 93, 191, 92, 53, 94, 92, 93, 125, 72, - - 73, 94, 74, 75, 189, 104, 76, 78, 104, 80, - 187, 133, 186, 125, 78, 78, 134, 185, 104, 103, - 78, 104, 78, 130, 149, 78, 131, 78, 78, 92, - 53, 114, 92, 93, 114, 149, 184, 94, 183, 115, - 195, 195, 182, 181, 179, 78, 78, 79, 79, 80, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 81, 79, 79, 79, 79, 79, 79, 81, - 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 79, 81, 81, 81, 81, - 81, 81, 81, 81, 81, 81, 70, 151, 95, 70, - - 171, 95, 172, 173, 174, 188, 190, 199, 180, 203, - 103, 180, 151, 200, 204, 178, 171, 190, 172, 173, - 174, 188, 103, 199, 180, 203, 177, 180, 200, 176, - 204, 205, 205, 175, 205, 205, 72, 73, 103, 74, - 75, 96, 170, 76, 78, 169, 80, 168, 206, 206, - 167, 78, 78, 166, 165, 164, 163, 78, 162, 78, - 161, 160, 78, 159, 78, 78, 158, 157, 156, 155, - 154, 153, 152, 150, 148, 147, 146, 145, 144, 143, - 142, 141, 78, 78, 40, 40, 40, 40, 40, 40, - 40, 45, 140, 139, 138, 45, 45, 46, 46, 46, - - 46, 46, 46, 46, 59, 137, 59, 79, 79, 79, - 79, 79, 79, 79, 91, 91, 91, 91, 91, 91, - 91, 194, 194, 194, 136, 194, 194, 194, 196, 135, - 196, 132, 196, 196, 196, 207, 207, 207, 207, 207, - 129, 207, 128, 124, 123, 120, 117, 116, 113, 80, - 112, 111, 110, 105, 101, 86, 85, 47, 82, 77, - 62, 58, 57, 56, 47, 209, 37, 11, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209 + 35, 66, 35, 35, 103, 36, 36, 37, 38, 35, + 37, 38, 35, 66, 214, 36, 42, 43, 42, 43, + 103, 39, 208, 44, 45, 44, 45, 42, 43, 93, + 94, 46, 40, 40, 44, 42, 43, 50, 62, 46, + 50, 63, 44, 55, 55, 55, 55, 56, 40, 40, + + 207, 57, 62, 65, 204, 63, 67, 68, 69, 67, + 71, 51, 50, 71, 65, 50, 72, 88, 89, 90, + 88, 95, 101, 52, 96, 101, 106, 108, 53, 104, + 54, 47, 67, 68, 69, 67, 51, 114, 47, 47, + 115, 105, 106, 108, 47, 104, 70, 110, 52, 47, + 110, 47, 47, 53, 203, 54, 55, 55, 55, 55, + 56, 74, 112, 113, 57, 102, 199, 127, 139, 47, + 70, 73, 128, 140, 73, 98, 55, 98, 98, 99, + 198, 71, 131, 100, 71, 74, 197, 72, 88, 89, + 90, 88, 120, 124, 195, 120, 125, 131, 193, 192, + + 121, 98, 55, 98, 98, 99, 132, 101, 157, 100, + 101, 75, 76, 133, 77, 78, 191, 110, 79, 82, + 110, 84, 132, 157, 133, 110, 82, 82, 110, 190, + 136, 109, 82, 137, 82, 155, 177, 82, 178, 82, + 82, 98, 55, 98, 98, 99, 155, 189, 120, 100, + 102, 120, 177, 188, 178, 187, 121, 82, 82, 83, + 83, 84, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 85, 83, 83, 83, 83, 83, + 83, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 83, 85, 85, + + 85, 85, 85, 85, 85, 85, 85, 85, 73, 185, + 196, 73, 98, 55, 98, 98, 99, 179, 180, 194, + 100, 196, 109, 98, 55, 98, 98, 99, 205, 186, + 206, 100, 186, 179, 180, 194, 186, 209, 210, 186, + 201, 201, 201, 109, 205, 206, 184, 183, 75, 76, + 109, 77, 78, 209, 210, 79, 82, 182, 84, 181, + 176, 175, 211, 82, 82, 211, 174, 211, 173, 82, + 211, 82, 172, 171, 82, 170, 82, 82, 169, 212, + 168, 167, 166, 165, 212, 164, 163, 162, 161, 160, + 159, 158, 156, 154, 82, 82, 41, 41, 41, 41, + + 41, 41, 41, 47, 153, 152, 151, 47, 47, 48, + 48, 48, 48, 48, 48, 48, 61, 150, 61, 83, + 83, 83, 83, 83, 83, 83, 97, 97, 97, 97, + 97, 97, 97, 200, 200, 149, 200, 200, 200, 200, + 202, 148, 147, 202, 202, 202, 202, 213, 213, 213, + 213, 213, 146, 213, 145, 144, 143, 142, 141, 138, + 135, 134, 130, 129, 126, 123, 122, 89, 86, 119, + 84, 80, 118, 117, 116, 111, 68, 107, 92, 91, + 49, 87, 86, 81, 80, 64, 60, 59, 58, 49, + 215, 11, 215, 215, 215, 215, 215, 215, 215, 215, + + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215 } ; -static const flex_int16_t yy_chk[518] = +static const flex_int16_t yy_chk[542] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, - 4, 28, 2, 4, 7, 2, 4, 6, 6, 8, - 6, 7, 7, 6, 9, 28, 8, 8, 9, 6, - 10, 9, 207, 29, 10, 17, 32, 10, 17, 198, - 6, 6, 18, 18, 31, 18, 18, 29, 32, 100, - 18, 33, 33, 193, 33, 31, 6, 6, 35, 17, - - 100, 35, 42, 42, 35, 42, 48, 51, 51, 48, - 52, 17, 187, 52, 186, 60, 17, 61, 17, 34, - 53, 53, 58, 53, 53, 58, 34, 34, 53, 61, - 48, 60, 34, 61, 34, 62, 89, 34, 64, 34, - 34, 89, 48, 65, 65, 74, 65, 48, 74, 48, - 179, 62, 54, 54, 64, 54, 54, 34, 34, 36, - 54, 68, 36, 71, 68, 58, 71, 68, 73, 73, - 99, 83, 83, 36, 83, 84, 87, 71, 84, 87, - 178, 91, 91, 84, 91, 91, 99, 92, 92, 91, - 92, 92, 175, 93, 93, 92, 93, 93, 98, 36, - - 36, 93, 36, 36, 172, 103, 36, 38, 103, 38, - 170, 108, 169, 98, 38, 38, 108, 168, 104, 103, - 38, 104, 38, 106, 125, 38, 106, 38, 38, 94, - 94, 114, 94, 94, 114, 125, 164, 94, 163, 114, - 182, 182, 162, 161, 159, 38, 38, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 39, 69, 127, 95, 69, - - 149, 95, 150, 151, 152, 171, 174, 189, 160, 199, - 69, 160, 127, 190, 200, 158, 149, 174, 150, 151, - 152, 171, 160, 189, 180, 199, 157, 180, 190, 156, - 200, 201, 205, 153, 201, 205, 69, 69, 180, 69, - 69, 95, 148, 69, 78, 147, 78, 146, 201, 205, - 145, 78, 78, 144, 141, 140, 139, 78, 138, 78, - 137, 136, 78, 135, 78, 78, 134, 133, 132, 131, - 130, 129, 128, 126, 124, 123, 122, 121, 120, 119, - 118, 117, 78, 78, 210, 210, 210, 210, 210, 210, - 210, 211, 116, 113, 112, 211, 211, 212, 212, 212, - - 212, 212, 212, 212, 213, 111, 213, 214, 214, 214, - 214, 214, 214, 214, 215, 215, 215, 215, 215, 215, - 215, 216, 216, 216, 110, 216, 216, 216, 217, 109, - 217, 107, 217, 217, 217, 218, 218, 218, 218, 218, - 105, 218, 101, 96, 90, 88, 86, 85, 82, 79, - 77, 76, 75, 72, 63, 50, 49, 46, 41, 37, - 30, 26, 25, 23, 15, 11, 5, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - - 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, - 209, 209, 209, 209, 209, 209, 209 + 4, 32, 2, 4, 62, 2, 4, 5, 5, 6, + 6, 6, 6, 32, 213, 6, 7, 7, 8, 8, + 62, 6, 204, 7, 7, 8, 8, 9, 9, 53, + 53, 9, 6, 6, 9, 10, 10, 17, 28, 10, + 17, 29, 10, 18, 18, 18, 18, 18, 6, 6, + + 199, 18, 28, 31, 193, 29, 33, 33, 33, 33, + 35, 17, 50, 35, 31, 50, 35, 44, 44, 44, + 44, 54, 60, 17, 54, 60, 64, 66, 17, 63, + 17, 34, 67, 67, 67, 67, 50, 77, 34, 34, + 77, 63, 64, 66, 34, 63, 34, 74, 50, 34, + 74, 34, 34, 50, 192, 50, 55, 55, 55, 55, + 55, 74, 76, 76, 55, 60, 185, 95, 114, 34, + 34, 36, 95, 114, 36, 56, 56, 56, 56, 56, + 184, 71, 104, 56, 71, 36, 181, 71, 88, 88, + 88, 88, 89, 93, 178, 89, 93, 104, 176, 175, + + 89, 97, 97, 97, 97, 97, 105, 101, 133, 97, + 101, 36, 36, 106, 36, 36, 174, 109, 36, 39, + 109, 39, 105, 133, 106, 110, 39, 39, 110, 170, + 112, 109, 39, 112, 39, 131, 155, 39, 156, 39, + 39, 98, 98, 98, 98, 98, 131, 169, 120, 98, + 101, 120, 155, 168, 156, 167, 120, 39, 39, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + + 40, 40, 40, 40, 40, 40, 40, 40, 72, 165, + 180, 72, 99, 99, 99, 99, 99, 157, 158, 177, + 99, 180, 72, 100, 100, 100, 100, 100, 195, 166, + 196, 100, 166, 157, 158, 177, 186, 205, 206, 186, + 188, 188, 188, 166, 195, 196, 164, 163, 72, 72, + 186, 72, 72, 205, 206, 72, 82, 162, 82, 159, + 154, 153, 207, 82, 82, 207, 152, 211, 151, 82, + 211, 82, 150, 147, 82, 146, 82, 82, 145, 207, + 144, 143, 142, 141, 211, 140, 139, 138, 137, 136, + 135, 134, 132, 130, 82, 82, 216, 216, 216, 216, + + 216, 216, 216, 217, 129, 128, 127, 217, 217, 218, + 218, 218, 218, 218, 218, 218, 219, 126, 219, 220, + 220, 220, 220, 220, 220, 220, 221, 221, 221, 221, + 221, 221, 221, 222, 222, 125, 222, 222, 222, 222, + 223, 124, 123, 223, 223, 223, 223, 224, 224, 224, + 224, 224, 122, 224, 119, 118, 117, 116, 115, 113, + 111, 107, 102, 96, 94, 92, 91, 90, 87, 86, + 83, 81, 80, 79, 78, 75, 69, 65, 52, 51, + 48, 43, 42, 38, 37, 30, 26, 25, 23, 15, + 11, 215, 215, 215, 215, 215, 215, 215, 215, 215, + + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215 } ; /* The intent behind this definition is that it'll catch @@ -1139,13 +1148,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 210 ) + if ( yy_current_state >= 216 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 468 ); + while ( yy_base[yy_current_state] != 492 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1733,7 +1742,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 210 ) + if ( yy_current_state >= 216 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -1762,11 +1771,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 210 ) + if ( yy_current_state >= 216 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 209); + yy_is_jam = (yy_current_state == 215); (void)yyg; return yy_is_jam ? 0 : yy_current_state; diff --git a/Source/LexerParser/cmFortranLexer.in.l b/Source/LexerParser/cmFortranLexer.in.l index 05769a1..fac3181 100644 --- a/Source/LexerParser/cmFortranLexer.in.l +++ b/Source/LexerParser/cmFortranLexer.in.l @@ -75,10 +75,10 @@ Modify cmFortranLexer.cxx: return STRING; } -<str_dq,str_sq>&[ \t]*\n | -<str_dq,str_sq>&[ \t]*\n[ \t]*& /* Ignore (continued strings, free fmt) */ +<str_dq,str_sq>&[ \t]*\r?\n | +<str_dq,str_sq>&[ \t]*\r?\n[ \t]*& /* Ignore (continued strings, free fmt) */ -<fixed_fmt,str_dq,str_sq>\n[ ]{5}[^ \t\n] { +<fixed_fmt,str_dq,str_sq>\r?\n[ ]{5}[^ \t\r\n] { if (cmFortranParser_GetOldStartcond(yyextra) == fixed_fmt) ; /* Ignore (cont. strings, fixed fmt) */ else @@ -132,15 +132,15 @@ $[ \t]*else { return F90PPR_ELSE; } $[ \t]*endif { return F90PPR_ENDIF; } /* Line continuations, possible involving comments. */ -&([ \t\n]*|!.*)* -&([ \t\n]*|!.*)*& +&([ \t\r\n]*|!.*)* +&([ \t\r\n]*|!.*)*& , { return COMMA; } :: { return DCOLON; } : { return COLON; } -<fixed_fmt>\n[ ]{5}[^ ] { return GARBAGE; } +<fixed_fmt>\r?\n[ ]{5}[^ ] { return GARBAGE; } =|=> { return ASSIGNMENT_OP; } @@ -159,13 +159,13 @@ $[ \t]*endif { return F90PPR_ENDIF; } \( { return LPAREN; } \) { return RPAREN; } -[^ \t\n\r:;,!'"a-zA-Z=&()]+ { return GARBAGE; } +[^ \t\r\n:;,!'"a-zA-Z=&()]+ { return GARBAGE; } ;|\n { return EOSTMT; } [ \t\r,] /* Ignore */ -\\[ \t]*\n /* Ignore line-endings preceded by \ */ +\\[ \t]*\r?\n /* Ignore line-endings preceded by \ */ . { return *yytext; } diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index b177296..5e5cc0b 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -548,7 +548,7 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 2 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 594 +#define YYLAST 432 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 41 @@ -557,7 +557,7 @@ union yyalloc /* YYNRULES -- Number of rules. */ #define YYNRULES 64 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 127 +#define YYNSTATES 121 /* YYMAXUTOK -- Last valid token kind. */ #define YYMAXUTOK 295 @@ -608,15 +608,15 @@ static const yytype_int8 yytranslate[] = #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ -static const yytype_int16 yyrline[] = +static const yytype_uint8 yyrline[] = { - 0, 106, 106, 106, 109, 113, 118, 127, 133, 140, - 145, 149, 154, 166, 171, 176, 181, 186, 191, 196, - 201, 206, 210, 214, 218, 222, 223, 228, 228, 228, - 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, - 234, 234, 235, 235, 236, 236, 237, 237, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256 + 0, 106, 106, 106, 109, 113, 118, 123, 129, 136, + 141, 145, 150, 162, 167, 172, 177, 182, 187, 192, + 197, 202, 206, 210, 214, 218, 219, 224, 224, 224, + 225, 225, 226, 226, 227, 227, 228, 228, 229, 229, + 230, 230, 231, 231, 232, 232, 233, 233, 236, 237, + 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252 }; #endif @@ -666,19 +666,19 @@ yysymbol_name (yysymbol_kind_t yysymbol) STATE-NUM. */ static const yytype_int16 yypact[] = { - -39, 21, -39, 1, -39, -20, -39, -39, -39, -39, + -39, 21, -39, 5, -39, -23, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, -39, -39, -39, -24, -18, 20, -8, - -3, 40, -39, 15, 16, 17, 19, 34, -39, -39, - -39, -39, -39, -39, 59, -39, -39, -39, -39, -39, - 36, 37, 38, -39, -39, -39, -39, -39, -39, 77, - 115, 130, 168, 183, -39, -39, -39, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -25, -19, 20, -8, + -15, -22, -39, -6, 14, 15, 16, 17, -39, -39, + -39, -39, -39, -39, 59, 49, 51, -39, 63, 64, + 35, 36, 37, -39, -39, -39, -39, -39, -39, 74, + 112, 127, 165, 180, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, - -39, -39, -39, 221, 236, 274, 289, -21, 26, -39, - 327, 342, 380, 395, 433, 448, -39, -39, -39, -39, - -39, -39, -39, -39, -39, 39, 41, 42, 486, -39, - -39, -39, -39, -39, -39, 18, -39, -39, -39, 43, - 501, 539, -39, -39, -39, 554, -39 + -39, -39, -39, -39, -39, -39, -39, -20, 43, -39, + 218, 233, 271, 286, 324, 339, -39, -39, -39, -39, + -39, 39, 40, 41, 377, -39, -39, -39, -39, -39, + -39, 46, 78, -39, -39, 50, -39, 392, 79, -39, + -39 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -690,15 +690,15 @@ static const yytype_int8 yydefact[] = 30, 33, 32, 34, 36, 38, 42, 40, 44, 35, 37, 39, 43, 41, 45, 46, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 46, 46, - 46, 46, 26, 46, 0, 46, 46, 4, 46, 46, + 46, 46, 26, 46, 0, 0, 0, 4, 0, 0, 0, 0, 0, 46, 46, 46, 46, 46, 46, 0, 0, 0, 0, 0, 15, 57, 56, 64, 62, 58, 59, 60, 61, 63, 55, 48, 49, 50, 51, 52, - 53, 54, 47, 0, 0, 0, 0, 0, 0, 46, + 53, 54, 47, 10, 13, 9, 6, 0, 0, 46, 0, 0, 0, 0, 0, 0, 21, 22, 23, 24, - 14, 10, 13, 9, 6, 0, 0, 0, 0, 5, - 16, 17, 18, 19, 20, 0, 46, 46, 11, 0, - 0, 0, 46, 7, 12, 0, 8 + 14, 0, 0, 0, 0, 5, 16, 17, 18, 19, + 20, 0, 0, 46, 11, 0, 7, 0, 0, 12, + 8 }; /* YYPGOTO[NTERM-NUM]. */ @@ -720,81 +720,70 @@ static const yytype_int8 yydefgoto[] = number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int8 yytable[] = { - 59, 60, 61, 62, 42, 63, 105, 83, 84, 106, - 85, 86, 43, 45, 46, 90, 91, 92, 93, 94, - 95, 2, 3, 47, 4, 49, 50, 5, 6, 7, + 59, 60, 61, 62, 51, 63, 52, 101, 42, 43, + 102, 53, 45, 46, 50, 90, 91, 92, 93, 94, + 95, 2, 3, 47, 4, 49, 54, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 54, 119, 55, - 56, 108, 57, 48, 107, 25, 26, 27, 28, 29, - 30, 31, 64, 65, 66, 67, 51, 58, 52, 87, - 88, 89, 115, 53, 116, 117, 122, 0, 120, 121, - 96, 65, 66, 67, 125, 68, 69, 70, 71, 72, + 18, 19, 20, 21, 22, 23, 24, 55, 56, 57, + 58, 104, 83, 48, 84, 25, 26, 27, 28, 29, + 30, 31, 64, 65, 66, 67, 85, 86, 87, 88, + 89, 103, 111, 112, 113, 117, 115, 96, 65, 66, + 67, 116, 120, 118, 0, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, - 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, - 75, 0, 76, 77, 78, 79, 80, 81, 97, 65, + 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, + 77, 78, 79, 80, 81, 97, 65, 66, 67, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 98, 65, 66, 67, 0, 0, 0, 0, 68, 69, + 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, + 79, 80, 81, 68, 69, 70, 71, 72, 73, 74, + 75, 0, 76, 77, 78, 79, 80, 81, 99, 65, 66, 67, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 98, 65, 66, 67, 0, 0, 0, + 0, 0, 0, 100, 65, 66, 67, 0, 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, - 81, 99, 65, 66, 67, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 100, 65, 66, 67, + 81, 105, 65, 66, 67, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 106, 65, 66, 67, 0, 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, - 78, 79, 80, 81, 101, 65, 66, 67, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, + 78, 79, 80, 81, 107, 65, 66, 67, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 108, 65, 66, 67, 0, 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, 68, 69, 70, 71, 72, 73, 74, 75, - 0, 76, 77, 78, 79, 80, 81, 103, 65, 66, + 0, 76, 77, 78, 79, 80, 81, 109, 65, 66, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 104, 65, 66, 67, 0, 0, 0, 0, + 0, 0, 110, 65, 66, 67, 0, 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, - 109, 65, 66, 67, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 110, 65, 66, 67, 0, + 114, 65, 66, 67, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 119, 65, 66, 67, 0, 0, 0, 0, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, 78, - 79, 80, 81, 111, 65, 66, 67, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 112, 65, - 66, 67, 0, 0, 0, 0, 68, 69, 70, 71, - 72, 73, 74, 75, 0, 76, 77, 78, 79, 80, - 81, 68, 69, 70, 71, 72, 73, 74, 75, 0, - 76, 77, 78, 79, 80, 81, 113, 65, 66, 67, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 114, 65, 66, 67, 0, 0, 0, 0, 68, - 69, 70, 71, 72, 73, 74, 75, 0, 76, 77, - 78, 79, 80, 81, 68, 69, 70, 71, 72, 73, - 74, 75, 0, 76, 77, 78, 79, 80, 81, 118, - 65, 66, 67, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 123, 65, 66, 67, 0, 0, - 0, 0, 68, 69, 70, 71, 72, 73, 74, 75, - 0, 76, 77, 78, 79, 80, 81, 68, 69, 70, - 71, 72, 73, 74, 75, 0, 76, 77, 78, 79, - 80, 81, 124, 65, 66, 67, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 126, 65, 66, - 67, 0, 0, 0, 0, 68, 69, 70, 71, 72, - 73, 74, 75, 0, 76, 77, 78, 79, 80, 81, - 68, 69, 70, 71, 72, 73, 74, 75, 0, 76, - 77, 78, 79, 80, 81 + 79, 80, 81 }; static const yytype_int8 yycheck[] = { - 38, 39, 40, 41, 3, 43, 27, 45, 46, 30, - 48, 49, 32, 37, 32, 53, 54, 55, 56, 57, - 58, 0, 1, 3, 3, 33, 29, 6, 7, 8, + 38, 39, 40, 41, 26, 43, 28, 27, 3, 32, + 30, 33, 37, 32, 29, 53, 54, 55, 56, 57, + 58, 0, 1, 3, 3, 33, 32, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 32, 30, 33, - 33, 89, 33, 33, 28, 34, 35, 36, 37, 38, - 39, 40, 3, 4, 5, 6, 26, 33, 28, 33, - 33, 33, 33, 33, 33, 33, 33, -1, 116, 117, - 3, 4, 5, 6, 122, 26, 27, 28, 29, 30, + 19, 20, 21, 22, 23, 24, 25, 33, 33, 33, + 33, 89, 3, 33, 3, 34, 35, 36, 37, 38, + 39, 40, 3, 4, 5, 6, 3, 3, 33, 33, + 33, 28, 33, 33, 33, 113, 30, 3, 4, 5, + 6, 3, 3, 33, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, - -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, + 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, + 36, 37, 38, 39, 40, 3, 4, 5, 6, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 3, 4, 5, 6, -1, -1, -1, -1, 26, 27, + 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, + 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 3, 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, @@ -822,28 +811,7 @@ static const yytype_int8 yycheck[] = -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, 37, - 38, 39, 40, 3, 4, 5, 6, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, - 5, 6, -1, -1, -1, -1, 26, 27, 28, 29, - 30, 31, 32, 33, -1, 35, 36, 37, 38, 39, - 40, 26, 27, 28, 29, 30, 31, 32, 33, -1, - 35, 36, 37, 38, 39, 40, 3, 4, 5, 6, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 3, 4, 5, 6, -1, -1, -1, -1, 26, - 27, 28, 29, 30, 31, 32, 33, -1, 35, 36, - 37, 38, 39, 40, 26, 27, 28, 29, 30, 31, - 32, 33, -1, 35, 36, 37, 38, 39, 40, 3, - 4, 5, 6, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, - -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, - -1, 35, 36, 37, 38, 39, 40, 26, 27, 28, - 29, 30, 31, 32, 33, -1, 35, 36, 37, 38, - 39, 40, 3, 4, 5, 6, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, - 6, -1, -1, -1, -1, 26, 27, 28, 29, 30, - 31, 32, 33, -1, 35, 36, 37, 38, 39, 40, - 26, 27, 28, 29, 30, 31, 32, 33, -1, 35, - 36, 37, 38, 39, 40 + 38, 39, 40 }; /* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of @@ -858,11 +826,11 @@ static const yytype_int8 yystos[] = 29, 26, 28, 33, 32, 33, 33, 33, 33, 53, 53, 53, 53, 53, 3, 4, 5, 6, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, - 39, 40, 54, 53, 53, 53, 53, 33, 33, 33, + 39, 40, 54, 3, 3, 3, 3, 33, 33, 33, 53, 53, 53, 53, 53, 53, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 27, 30, 28, 53, 3, - 3, 3, 3, 3, 3, 33, 33, 33, 3, 30, - 53, 53, 33, 3, 3, 53, 3 + 3, 27, 30, 28, 53, 3, 3, 3, 3, 3, + 3, 33, 33, 33, 3, 30, 3, 53, 33, 3, + 3 }; /* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ @@ -880,8 +848,8 @@ static const yytype_int8 yyr1[] = /* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ static const yytype_int8 yyr2[] = { - 0, 2, 0, 2, 2, 4, 4, 7, 9, 4, - 4, 5, 7, 4, 4, 3, 4, 4, 4, 4, + 0, 2, 0, 2, 2, 4, 3, 6, 8, 3, + 3, 5, 7, 3, 4, 3, 4, 4, 4, 4, 4, 3, 3, 3, 3, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, 1, 1, @@ -1361,19 +1329,19 @@ yydestruct (const char *yymsg, case YYSYMBOL_STRING: /* STRING */ #line 100 "cmFortranParser.y" { free(((*yyvaluep).string)); } -#line 1365 "cmFortranParser.cxx" +#line 1333 "cmFortranParser.cxx" break; case YYSYMBOL_WORD: /* WORD */ #line 100 "cmFortranParser.y" { free(((*yyvaluep).string)); } -#line 1371 "cmFortranParser.cxx" +#line 1339 "cmFortranParser.cxx" break; case YYSYMBOL_CPP_INCLUDE_ANGLE: /* CPP_INCLUDE_ANGLE */ #line 100 "cmFortranParser.y" { free(((*yyvaluep).string)); } -#line 1377 "cmFortranParser.cxx" +#line 1345 "cmFortranParser.cxx" break; default: @@ -1655,7 +1623,7 @@ yyreduce: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); } -#line 1659 "cmFortranParser.cxx" +#line 1627 "cmFortranParser.cxx" break; case 5: /* stmt: USE WORD other EOSTMT */ @@ -1665,77 +1633,73 @@ yyreduce: cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1669 "cmFortranParser.cxx" +#line 1637 "cmFortranParser.cxx" break; - case 6: /* stmt: MODULE WORD other EOSTMT */ + case 6: /* stmt: MODULE WORD EOSTMT */ #line 118 "cmFortranParser.y" - { + { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); - if (cmsysString_strcasecmp((yyvsp[-2].string), "function") != 0 && - cmsysString_strcasecmp((yyvsp[-2].string), "procedure") != 0 && - cmsysString_strcasecmp((yyvsp[-2].string), "subroutine") != 0) { - cmFortranParser_RuleModule(parser, (yyvsp[-2].string)); - } - free((yyvsp[-2].string)); + cmFortranParser_RuleModule(parser, (yyvsp[-1].string)); + free((yyvsp[-1].string)); } -#line 1683 "cmFortranParser.cxx" +#line 1647 "cmFortranParser.cxx" break; - case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT */ -#line 127 "cmFortranParser.y" - { + case 7: /* stmt: SUBMODULE LPAREN WORD RPAREN WORD EOSTMT */ +#line 123 "cmFortranParser.y" + { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); - cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string)); - free((yyvsp[-4].string)); - free((yyvsp[-2].string)); + cmFortranParser_RuleSubmodule(parser, (yyvsp[-3].string), (yyvsp[-1].string)); + free((yyvsp[-3].string)); + free((yyvsp[-1].string)); } -#line 1694 "cmFortranParser.cxx" +#line 1658 "cmFortranParser.cxx" break; - case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT */ -#line 133 "cmFortranParser.y" - { + case 8: /* stmt: SUBMODULE LPAREN WORD COLON WORD RPAREN WORD EOSTMT */ +#line 129 "cmFortranParser.y" + { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); - cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); - free((yyvsp[-6].string)); - free((yyvsp[-4].string)); - free((yyvsp[-2].string)); + cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-5].string), (yyvsp[-3].string), (yyvsp[-1].string)); + free((yyvsp[-5].string)); + free((yyvsp[-3].string)); + free((yyvsp[-1].string)); } -#line 1706 "cmFortranParser.cxx" +#line 1670 "cmFortranParser.cxx" break; - case 9: /* stmt: INTERFACE WORD other EOSTMT */ -#line 140 "cmFortranParser.y" - { + case 9: /* stmt: INTERFACE WORD EOSTMT */ +#line 136 "cmFortranParser.y" + { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); - free((yyvsp[-2].string)); + free((yyvsp[-1].string)); } -#line 1716 "cmFortranParser.cxx" +#line 1680 "cmFortranParser.cxx" break; - case 10: /* stmt: END INTERFACE other EOSTMT */ -#line 145 "cmFortranParser.y" - { + case 10: /* stmt: END INTERFACE EOSTMT */ +#line 141 "cmFortranParser.y" + { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } -#line 1725 "cmFortranParser.cxx" +#line 1689 "cmFortranParser.cxx" break; case 11: /* stmt: USE DCOLON WORD other EOSTMT */ -#line 149 "cmFortranParser.y" +#line 145 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1735 "cmFortranParser.cxx" +#line 1699 "cmFortranParser.cxx" break; case 12: /* stmt: USE COMMA WORD DCOLON WORD other EOSTMT */ -#line 154 "cmFortranParser.y" +#line 150 "cmFortranParser.y" { if (cmsysString_strcasecmp((yyvsp[-4].string), "non_intrinsic") == 0) { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); @@ -1748,139 +1712,139 @@ yyreduce: free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1752 "cmFortranParser.cxx" +#line 1716 "cmFortranParser.cxx" break; - case 13: /* stmt: INCLUDE STRING other EOSTMT */ -#line 166 "cmFortranParser.y" - { + case 13: /* stmt: INCLUDE STRING EOSTMT */ +#line 162 "cmFortranParser.y" + { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); - cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); - free((yyvsp[-2].string)); + cmFortranParser_RuleInclude(parser, (yyvsp[-1].string)); + free((yyvsp[-1].string)); } -#line 1762 "cmFortranParser.cxx" +#line 1726 "cmFortranParser.cxx" break; case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */ -#line 171 "cmFortranParser.y" +#line 167 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1772 "cmFortranParser.cxx" +#line 1736 "cmFortranParser.cxx" break; case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */ -#line 176 "cmFortranParser.y" +#line 172 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1782 "cmFortranParser.cxx" +#line 1746 "cmFortranParser.cxx" break; case 16: /* stmt: include STRING other EOSTMT */ -#line 181 "cmFortranParser.y" +#line 177 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1792 "cmFortranParser.cxx" +#line 1756 "cmFortranParser.cxx" break; case 17: /* stmt: define WORD other EOSTMT */ -#line 186 "cmFortranParser.y" +#line 182 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1802 "cmFortranParser.cxx" +#line 1766 "cmFortranParser.cxx" break; case 18: /* stmt: undef WORD other EOSTMT */ -#line 191 "cmFortranParser.y" +#line 187 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1812 "cmFortranParser.cxx" +#line 1776 "cmFortranParser.cxx" break; case 19: /* stmt: ifdef WORD other EOSTMT */ -#line 196 "cmFortranParser.y" +#line 192 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1822 "cmFortranParser.cxx" +#line 1786 "cmFortranParser.cxx" break; case 20: /* stmt: ifndef WORD other EOSTMT */ -#line 201 "cmFortranParser.y" +#line 197 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1832 "cmFortranParser.cxx" +#line 1796 "cmFortranParser.cxx" break; case 21: /* stmt: if other EOSTMT */ -#line 206 "cmFortranParser.y" +#line 202 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1841 "cmFortranParser.cxx" +#line 1805 "cmFortranParser.cxx" break; case 22: /* stmt: elif other EOSTMT */ -#line 210 "cmFortranParser.y" +#line 206 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1850 "cmFortranParser.cxx" +#line 1814 "cmFortranParser.cxx" break; case 23: /* stmt: else other EOSTMT */ -#line 214 "cmFortranParser.y" +#line 210 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1859 "cmFortranParser.cxx" +#line 1823 "cmFortranParser.cxx" break; case 24: /* stmt: endif other EOSTMT */ -#line 218 "cmFortranParser.y" +#line 214 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1868 "cmFortranParser.cxx" +#line 1832 "cmFortranParser.cxx" break; case 48: /* misc_code: WORD */ -#line 240 "cmFortranParser.y" +#line 236 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1874 "cmFortranParser.cxx" +#line 1838 "cmFortranParser.cxx" break; case 55: /* misc_code: STRING */ -#line 247 "cmFortranParser.y" +#line 243 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1880 "cmFortranParser.cxx" +#line 1844 "cmFortranParser.cxx" break; -#line 1884 "cmFortranParser.cxx" +#line 1848 "cmFortranParser.cxx" default: break; } @@ -2104,6 +2068,6 @@ yyreturnlab: return yyresult; } -#line 259 "cmFortranParser.y" +#line 255 "cmFortranParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y index 07ca630..a5c8976 100644 --- a/Source/LexerParser/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -115,34 +115,30 @@ stmt: cmFortranParser_RuleUse(parser, $2); free($2); } -| MODULE WORD other EOSTMT { +| MODULE WORD EOSTMT { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); - if (cmsysString_strcasecmp($2, "function") != 0 && - cmsysString_strcasecmp($2, "procedure") != 0 && - cmsysString_strcasecmp($2, "subroutine") != 0) { - cmFortranParser_RuleModule(parser, $2); - } + cmFortranParser_RuleModule(parser, $2); free($2); } -| SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT { +| SUBMODULE LPAREN WORD RPAREN WORD EOSTMT { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmodule(parser, $3, $5); free($3); free($5); } -| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT { +| SUBMODULE LPAREN WORD COLON WORD RPAREN WORD EOSTMT { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleSubmoduleNested(parser, $3, $5, $7); free($3); free($5); free($7); } -| INTERFACE WORD other EOSTMT { +| INTERFACE WORD EOSTMT { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, true); free($2); } -| END INTERFACE other EOSTMT { +| END INTERFACE EOSTMT { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_SetInInterface(parser, false); } @@ -163,7 +159,7 @@ stmt: free($3); free($5); } -| INCLUDE STRING other EOSTMT { +| INCLUDE STRING EOSTMT { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, $2); free($2); diff --git a/Source/Modules/CMakeBuildUtilities.cmake b/Source/Modules/CMakeBuildUtilities.cmake new file mode 100644 index 0000000..5cfb0e7 --- /dev/null +++ b/Source/Modules/CMakeBuildUtilities.cmake @@ -0,0 +1,379 @@ +#----------------------------------------------------------------------- +# Build the utilities used by CMake +# +# Originally it was a macro in the root `CMakeLists.txt` with the comment +# "Simply to improve readability...". +# However, as part of the modernization refactoring it was moved into a +# separate file cuz adding library alises wasn't possible inside the +# macro. +#----------------------------------------------------------------------- + +# Suppress unnecessary checks in third-party code. +include(Utilities/cmThirdPartyChecks.cmake) + +#--------------------------------------------------------------------- +# Create the kwsys library for CMake. +set(KWSYS_NAMESPACE cmsys) +set(KWSYS_USE_SystemTools 1) +set(KWSYS_USE_Directory 1) +set(KWSYS_USE_RegularExpression 1) +set(KWSYS_USE_Base64 1) +set(KWSYS_USE_MD5 1) +set(KWSYS_USE_Process 1) +set(KWSYS_USE_CommandLineArguments 1) +set(KWSYS_USE_ConsoleBuf 1) +set(KWSYS_HEADER_ROOT ${CMake_BINARY_DIR}/Source) +set(KWSYS_INSTALL_DOC_DIR "${CMAKE_DOC_DIR}") +if(CMake_NO_CXX_STANDARD) + set(KWSYS_CXX_STANDARD "") +endif() +if(CMake_NO_SELF_BACKTRACE) + set(KWSYS_NO_EXECINFO 1) +endif() +if(WIN32) + # FIXME: Teach KWSys to hard-code these checks on Windows. + set(KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC_COMPILED 0) + set(KWSYS_C_HAS_PTRDIFF_T_COMPILED 1) + set(KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H_COMPILED 1) + set(KWSYS_CXX_HAS_RLIMIT64_COMPILED 0) + set(KWSYS_CXX_HAS_SETENV_COMPILED 0) + set(KWSYS_CXX_HAS_UNSETENV_COMPILED 0) + set(KWSYS_CXX_HAS_UTIMENSAT_COMPILED 0) + set(KWSYS_CXX_HAS_UTIMES_COMPILED 0) + set(KWSYS_CXX_STAT_HAS_ST_MTIM_COMPILED 0) + set(KWSYS_CXX_STAT_HAS_ST_MTIMESPEC_COMPILED 0) + set(KWSYS_STL_HAS_WSTRING_COMPILED 1) + set(KWSYS_SYS_HAS_IFADDRS_H 0) +endif() +add_subdirectory(Source/kwsys) +set(kwsys_folder "Utilities/KWSys") +CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE} "${kwsys_folder}") +CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}_c "${kwsys_folder}") +if(BUILD_TESTING) + CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestDynload "${kwsys_folder}") + CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestProcess "${kwsys_folder}") + CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestsC "${kwsys_folder}") + CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestsCxx "${kwsys_folder}") + CMAKE_SET_TARGET_FOLDER(${KWSYS_NAMESPACE}TestSharedForward "${kwsys_folder}") +endif() + +#--------------------------------------------------------------------- +# Setup third-party libraries. +# Everything in the tree should be able to include files from the +# Utilities directory. +if((CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400") AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # using -isystem option generate error "template with C linkage" + include_directories("${CMake_SOURCE_DIR}/Utilities/std") +else() + include_directories(SYSTEM "${CMake_SOURCE_DIR}/Utilities/std") +endif() + +include_directories("${CMake_BINARY_DIR}/Utilities") +if((CMAKE_SYSTEM_NAME STREQUAL "AIX" OR CMAKE_SYSTEM_NAME STREQUAL "OS400") AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # using -isystem option generate error "template with C linkage" + include_directories("${CMake_SOURCE_DIR}/Utilities") +else() + include_directories(SYSTEM "${CMake_SOURCE_DIR}/Utilities") +endif() + +#--------------------------------------------------------------------- +# Build CMake std library for CMake and CTest. +add_subdirectory(Utilities/std) +CMAKE_SET_TARGET_FOLDER(cmstd "Utilities/std") + +# check for the use of system libraries versus builtin ones +# (a macro defined in this file) +CMAKE_HANDLE_SYSTEM_LIBRARIES() + +if(CMAKE_USE_SYSTEM_KWIML) + find_package(KWIML 1.0) + if(NOT KWIML_FOUND) + message(FATAL_ERROR "CMAKE_USE_SYSTEM_KWIML is ON but KWIML is not found!") + endif() +else() + if(BUILD_TESTING) + set(KWIML_TEST_ENABLE 1) + endif() + add_subdirectory(Utilities/KWIML) +endif() + +if(CMAKE_USE_SYSTEM_LIBRHASH) + find_package(LibRHash) + if(NOT LibRHash_FOUND) + message(FATAL_ERROR + "CMAKE_USE_SYSTEM_LIBRHASH is ON but LibRHash is not found!") + endif() +else() + add_subdirectory(Utilities/cmlibrhash) + add_library(LibRHash::LibRHash ALIAS cmlibrhash) + CMAKE_SET_TARGET_FOLDER(cmlibrhash "Utilities/3rdParty") +endif() + +#--------------------------------------------------------------------- +# Build zlib library for Curl, CMake, and CTest. +if(CMAKE_USE_SYSTEM_ZLIB) + find_package(ZLIB) + if(NOT ZLIB_FOUND) + message(FATAL_ERROR + "CMAKE_USE_SYSTEM_ZLIB is ON but a zlib is not found!") + endif() +else() + if(NOT POLICY CMP0102) # CMake < 3.17 + # Store in cache to protect from mark_as_advanced. + set(ZLIB_INCLUDE_DIR ${CMake_SOURCE_DIR}/Utilities CACHE PATH "") + else() + set(ZLIB_INCLUDE_DIR ${CMake_SOURCE_DIR}/Utilities) + endif() + set(ZLIB_LIBRARY cmzlib) + set(WITHOUT_ZLIB_DLL "") + set(WITHOUT_ZLIB_DLL_WITH_LIB cmzlib) + set(ZLIB_DLL "") + set(ZLIB_DLL_WITH_LIB cmzlib) + set(ZLIB_WINAPI "") + set(ZLIB_WINAPI_COMPILED 0) + set(ZLIB_WINAPI_WITH_LIB cmzlib) + add_subdirectory(Utilities/cmzlib) + add_library(ZLIB::ZLIB ALIAS cmzlib) + CMAKE_SET_TARGET_FOLDER(cmzlib "Utilities/3rdParty") +endif() + +#--------------------------------------------------------------------- +# Build Curl library for CTest. +if(CMAKE_USE_SYSTEM_CURL) + find_package(CURL) + if(NOT CURL_FOUND) + message(FATAL_ERROR + "CMAKE_USE_SYSTEM_CURL is ON but a curl is not found!") + endif() +else() + if(CMAKE_TESTS_CDASH_SERVER) + set(CMAKE_CURL_TEST_URL "${CMAKE_TESTS_CDASH_SERVER}/user.php") + endif() + set(_CMAKE_USE_OPENSSL_DEFAULT OFF) + if(NOT DEFINED CMAKE_USE_OPENSSL AND NOT WIN32 AND NOT APPLE + AND CMAKE_SYSTEM_NAME MATCHES "(Linux|FreeBSD)") + set(_CMAKE_USE_OPENSSL_DEFAULT ON) + endif() + option(CMAKE_USE_OPENSSL "Use OpenSSL." ${_CMAKE_USE_OPENSSL_DEFAULT}) + mark_as_advanced(CMAKE_USE_OPENSSL) + if(CMAKE_USE_OPENSSL) + set(CURL_CA_BUNDLE "" CACHE FILEPATH "Path to SSL CA Certificate Bundle") + set(CURL_CA_PATH "" CACHE PATH "Path to SSL CA Certificate Directory") + mark_as_advanced(CURL_CA_BUNDLE CURL_CA_PATH) + endif() + if(NOT CMAKE_USE_SYSTEM_NGHTTP2) + # Tell curl's FindNGHTTP2 module to use our library. + set(NGHTTP2_LIBRARY cmnghttp2) + set(NGHTTP2_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmnghttp2/lib/includes) + endif() + add_subdirectory(Utilities/cmcurl) + add_library(CURL::libcurl ALIAS cmcurl) + CMAKE_SET_TARGET_FOLDER(cmcurl "Utilities/3rdParty") + CMAKE_SET_TARGET_FOLDER(LIBCURL "Utilities/3rdParty") + if(NOT CMAKE_USE_SYSTEM_NGHTTP2) + # Configure after curl to re-use some check results. + add_subdirectory(Utilities/cmnghttp2) + CMAKE_SET_TARGET_FOLDER(cmnghttp2 "Utilities/3rdParty") + endif() +endif() + +#--------------------------------------------------------------------- +# Build expat library for CMake, CTest, and libarchive. +if(CMAKE_USE_SYSTEM_EXPAT) + find_package(EXPAT) + if(NOT EXPAT_FOUND) + message(FATAL_ERROR + "CMAKE_USE_SYSTEM_EXPAT is ON but a expat is not found!") + endif() + set(CMAKE_EXPAT_INCLUDES ${EXPAT_INCLUDE_DIRS}) + set(CMAKE_EXPAT_LIBRARIES ${EXPAT_LIBRARIES}) +else() + set(CMAKE_EXPAT_INCLUDES) + set(CMAKE_EXPAT_LIBRARIES cmexpat) + add_subdirectory(Utilities/cmexpat) + add_library(EXPAT::EXPAT ALIAS cmexpat) + CMAKE_SET_TARGET_FOLDER(cmexpat "Utilities/3rdParty") +endif() + +#--------------------------------------------------------------------- +# Build or use system libbz2 for libarchive. +if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE) + if(CMAKE_USE_SYSTEM_BZIP2) + find_package(BZip2) + else() + set(BZIP2_INCLUDE_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmbzip2") + set(BZIP2_LIBRARIES cmbzip2) + set(BZIP2_NEED_PREFIX "") + set(USE_BZIP2_DLL "") + set(USE_BZIP2_DLL_WITH_LIB cmbzip2) + set(USE_BZIP2_STATIC "") + set(USE_BZIP2_STATIC_WITH_LIB cmbzip2) + add_subdirectory(Utilities/cmbzip2) + CMAKE_SET_TARGET_FOLDER(cmbzip2 "Utilities/3rdParty") + endif() +endif() + +#--------------------------------------------------------------------- +# Build or use system zstd for libarchive. +if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE) + if(NOT CMAKE_USE_SYSTEM_ZSTD) + set(ZSTD_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmzstd") + set(ZSTD_LIBRARY cmzstd) + add_subdirectory(Utilities/cmzstd) + CMAKE_SET_TARGET_FOLDER(cmzstd "Utilities/3rdParty") + endif() +endif() + +#--------------------------------------------------------------------- +# Build or use system liblzma for libarchive. +if(NOT CMAKE_USE_SYSTEM_LIBARCHIVE) + if(CMAKE_USE_SYSTEM_LIBLZMA) + find_package(LibLZMA) + if(NOT LIBLZMA_FOUND) + message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBLZMA is ON but LibLZMA is not found!") + endif() + else() + add_subdirectory(Utilities/cmliblzma) + CMAKE_SET_TARGET_FOLDER(cmliblzma "Utilities/3rdParty") + set(LIBLZMA_HAS_AUTO_DECODER 1) + set(LIBLZMA_HAS_EASY_ENCODER 1) + set(LIBLZMA_HAS_LZMA_PRESET 1) + set(LIBLZMA_INCLUDE_DIR + "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/cmliblzma/liblzma/api") + set(LIBLZMA_LIBRARY cmliblzma) + set(HAVE_LZMA_STREAM_ENCODER_MT 1) + endif() +endif() + +#--------------------------------------------------------------------- +# Build or use system libarchive for CMake and CTest. +if(CMAKE_USE_SYSTEM_LIBARCHIVE) + find_package(LibArchive 3.3.3) + if(NOT LibArchive_FOUND) + message(FATAL_ERROR "CMAKE_USE_SYSTEM_LIBARCHIVE is ON but LibArchive is not found!") + endif() + # NOTE `FindLibArchive` got imported targets support since 3.17 + if (NOT TARGET LibArchive::LibArchive) + add_library(LibArchive::LibArchive UNKNOWN IMPORTED) + set_target_properties(LibArchive::LibArchive PROPERTIES + IMPORTED_LOCATION "${LibArchive_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${LibArchive_INCLUDE_DIRS}") + endif () +else() + set(EXPAT_INCLUDE_DIR ${CMAKE_EXPAT_INCLUDES}) + set(EXPAT_LIBRARY ${CMAKE_EXPAT_LIBRARIES}) + set(ENABLE_MBEDTLS OFF) + set(ENABLE_NETTLE OFF) + if(DEFINED CMAKE_USE_OPENSSL) + set(ENABLE_OPENSSL "${CMAKE_USE_OPENSSL}") + else() + set(ENABLE_OPENSSL OFF) + endif() + set(ENABLE_LIBB2 OFF) + set(ENABLE_LZ4 OFF) + set(ENABLE_LZO OFF) + set(ENABLE_LZMA ON) + set(ENABLE_ZSTD ON) + set(ENABLE_ZLIB ON) + set(ENABLE_BZip2 ON) + set(ENABLE_LIBXML2 OFF) + set(ENABLE_EXPAT OFF) + set(ENABLE_PCREPOSIX OFF) + set(ENABLE_LibGCC OFF) + set(ENABLE_CNG OFF) + set(ENABLE_TAR OFF) + set(ENABLE_TAR_SHARED OFF) + set(ENABLE_CPIO OFF) + set(ENABLE_CPIO_SHARED OFF) + set(ENABLE_CAT OFF) + set(ENABLE_CAT_SHARED OFF) + set(ENABLE_XATTR OFF) + set(ENABLE_ACL OFF) + set(ENABLE_ICONV OFF) + set(ENABLE_TEST OFF) + set(ENABLE_COVERAGE OFF) + set(ENABLE_INSTALL OFF) + set(POSIX_REGEX_LIB "" CACHE INTERNAL "libarchive: No POSIX regular expression support") + set(ENABLE_SAFESEH "" CACHE INTERNAL "libarchive: No /SAFESEH linker flag") + set(WINDOWS_VERSION "WIN7" CACHE INTERNAL "libarchive: Set Windows version to use (Windows only)") + add_subdirectory(Utilities/cmlibarchive) + add_library(LibArchive::LibArchive ALIAS cmlibarchive) + target_compile_definitions(cmlibarchive INTERFACE LIBARCHIVE_STATIC) + CMAKE_SET_TARGET_FOLDER(cmlibarchive "Utilities/3rdParty") +endif() + +#--------------------------------------------------------------------- +# Build jsoncpp library. +if(CMAKE_USE_SYSTEM_JSONCPP) + find_package(JsonCpp 1.6.0) + if(NOT JsonCpp_FOUND) + message(FATAL_ERROR + "CMAKE_USE_SYSTEM_JSONCPP is ON but a JsonCpp is not found!") + endif() + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang") + set_property(TARGET JsonCpp::JsonCpp APPEND PROPERTY + INTERFACE_COMPILE_OPTIONS -Wno-deprecated-declarations) + endif() +else() + add_subdirectory(Utilities/cmjsoncpp) + add_library(JsonCpp::JsonCpp ALIAS cmjsoncpp) + CMAKE_SET_TARGET_FOLDER(cmjsoncpp "Utilities/3rdParty") +endif() + +#--------------------------------------------------------------------- +# Build libuv library. +if(CMAKE_USE_SYSTEM_LIBUV) + if(WIN32) + find_package(LibUV 1.38.0) + else() + find_package(LibUV 1.28.0) + endif() + if(NOT LIBUV_FOUND) + message(FATAL_ERROR + "CMAKE_USE_SYSTEM_LIBUV is ON but a libuv is not found!") + endif() +else() + add_subdirectory(Utilities/cmlibuv) + add_library(LibUV::LibUV ALIAS cmlibuv) + CMAKE_SET_TARGET_FOLDER(cmlibuv "Utilities/3rdParty") +endif() + +#--------------------------------------------------------------------- +# Use curses? +if(NOT DEFINED BUILD_CursesDialog) + if(UNIX) + include(${CMake_SOURCE_DIR}/Source/Checks/Curses.cmake) + set(BUILD_CursesDialog_DEFAULT "${CMakeCheckCurses_COMPILED}") + elseif(WIN32) + set(BUILD_CursesDialog_DEFAULT "OFF") + endif() + option(BUILD_CursesDialog "Build the CMake Curses Dialog ccmake" "${BUILD_CursesDialog_DEFAULT}") +endif() +if(BUILD_CursesDialog) + if(UNIX) + set(CURSES_NEED_NCURSES TRUE) + find_package(Curses) + if(NOT CURSES_FOUND) + message(WARNING + "'ccmake' will not be built because Curses was not found.\n" + "Turn off BUILD_CursesDialog to suppress this message." + ) + set(BUILD_CursesDialog 0) + endif() + elseif(WIN32) + # FIXME: Add support for system-provided pdcurses. + add_subdirectory(Utilities/cmpdcurses) + set(CURSES_LIBRARY cmpdcurses) + set(CURSES_INCLUDE_PATH "") # cmpdcurses has usage requirements + set(CMAKE_USE_SYSTEM_FORM 0) + set(HAVE_CURSES_USE_DEFAULT_COLORS 1) + endif() +endif() +if(BUILD_CursesDialog) + if(NOT CMAKE_USE_SYSTEM_FORM) + add_subdirectory(Source/CursesDialog/form) + elseif(NOT CURSES_FORM_LIBRARY) + message(FATAL_ERROR "CMAKE_USE_SYSTEM_FORM in ON but CURSES_FORM_LIBRARY is not set!") + endif() +endif() diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 0c263bb..a41b237 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -3,7 +3,7 @@ project(QtDialog) CMake_OPTIONAL_COMPONENT(cmake-gui) -set (QT_COMPONENTS +set(QT_COMPONENTS Core Widgets Gui @@ -41,8 +41,8 @@ set(CMake_QT_EXTRA_LIBRARIES) # Try to find the package WinExtras for the task bar progress if(WIN32) find_package(Qt${INSTALLED_QT_VERSION}WinExtras QUIET) - if (Qt${INSTALLED_QT_VERSION}WinExtras_FOUND) - add_definitions(-DQT_WINEXTRAS) + if(Qt${INSTALLED_QT_VERSION}WinExtras_FOUND) + add_compile_definitions(QT_WINEXTRAS) list(APPEND CMake_QT_EXTRA_LIBRARIES Qt${INSTALLED_QT_VERSION}::WinExtras) list(APPEND QT_COMPONENTS WinExtras) endif() @@ -100,14 +100,14 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) endif() endmacro() macro(install_qt_plugins _comps _plugins_var) - foreach(_qt_comp ${${_comps}}) - if (INSTALLED_QT_VERSION VERSION_LESS 6) + foreach(_qt_comp IN LISTS ${_comps}) + if(INSTALLED_QT_VERSION VERSION_LESS 6) set(_qt_module_plugins ${Qt${INSTALLED_QT_VERSION}${_qt_comp}_PLUGINS}) else() get_target_property(_qt_module_plugins Qt${INSTALLED_QT_VERSION}::${_qt_comp} QT_PLUGINS) endif() - foreach(_qt_plugin ${_qt_module_plugins}) - if (INSTALLED_QT_VERSION VERSION_GREATER_EQUAL 6) + foreach(_qt_plugin IN LISTS _qt_module_plugins) + if(INSTALLED_QT_VERSION VERSION_GREATER_EQUAL 6) # Qt6 provides the plugins as individual packages that need to be found. find_package(Qt${INSTALLED_QT_VERSION}${_qt_plugin} QUIET PATHS ${Qt${INSTALLED_QT_VERSION}${_qt_comp}_DIR}) @@ -117,7 +117,7 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) endforeach() endmacro() if(APPLE) - if (INSTALLED_QT_VERSION VERSION_EQUAL 5) + if(INSTALLED_QT_VERSION VERSION_EQUAL 5) install_qt_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS) if(TARGET Qt5::QMacStylePlugin) install_qt_plugin("Qt5::QMacStylePlugin" QT_PLUGINS) @@ -132,7 +132,7 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources" ${COMPONENT}) elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES) - if (INSTALLED_QT_VERSION VERSION_EQUAL 5) + if(INSTALLED_QT_VERSION VERSION_EQUAL 5) install_qt_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS) else() # FIXME: Minimize plugins for Qt6. @@ -152,7 +152,10 @@ if(APPLE) get_filename_component(Qt_BIN_DIR "${Qt_BIN_DIR}" PATH) endif() -set(SRCS +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +add_library( + CMakeGUILib STATIC AddCacheEntry.cxx AddCacheEntry.h CMakeSetupDialog.cxx @@ -179,6 +182,16 @@ set(SRCS WarningMessagesDialog.cxx WarningMessagesDialog.h ) +# CMake_QT_EXTRA_LIBRARIES have to come before the main libraries on the link line +target_link_libraries( + CMakeGUILib + PUBLIC + CMakeLib + ${CMake_QT_EXTRA_LIBRARIES} + Qt${INSTALLED_QT_VERSION}::Core + Qt${INSTALLED_QT_VERSION}::Widgets + ) + set(UI_SRCS CMakeSetupDialog.ui Compilers.ui @@ -204,7 +217,7 @@ set(MOC_SRCS ) set(QRC_SRCS CMakeSetup.qrc) -if (INSTALLED_QT_VERSION VERSION_LESS 6) +if(INSTALLED_QT_VERSION VERSION_LESS 6) qt5_wrap_ui(UI_BUILT_SRCS ${UI_SRCS}) qt5_wrap_cpp(MOC_BUILT_SRCS ${MOC_SRCS}) qt5_add_resources(QRC_BUILT_SRCS ${QRC_SRCS}) @@ -215,15 +228,18 @@ else() endif() add_library(CMakeGUIQRCLib OBJECT ${QRC_BUILT_SRCS}) -if (FALSE) # CMake's bootstrap binary does not support automoc +if(FALSE) # CMake's bootstrap binary does not support automoc set(CMAKE_AUTOMOC 1) set(CMAKE_AUTORCC 1) set(CMAKE_AUTOUIC 1) -else () - list(APPEND SRCS - ${UI_BUILT_SRCS} - ${MOC_BUILT_SRCS}) -endif () +else() + target_sources( + CMakeGUILib + PRIVATE + ${UI_BUILT_SRCS} + ${MOC_BUILT_SRCS} + ) +endif() if(USE_LGPL) install(FILES ${CMake_SOURCE_DIR}/Licenses/LGPLv${USE_LGPL}.txt @@ -233,22 +249,20 @@ if(USE_LGPL) PROPERTY COMPILE_DEFINITIONS USE_LGPL="${USE_LGPL}") endif() -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -add_library(CMakeGUILib STATIC ${SRCS}) -# CMake_QT_EXTRA_LIBRARIES have to come before the main libraries on the link line -target_link_libraries(CMakeGUILib PUBLIC CMakeLib ${CMake_QT_EXTRA_LIBRARIES} - Qt${INSTALLED_QT_VERSION}::Core Qt${INSTALLED_QT_VERSION}::Widgets) - add_library(CMakeGUIMainLib STATIC CMakeSetup.cxx) -target_link_libraries(CMakeGUIMainLib PUBLIC CMakeGUILib) +target_link_libraries( + CMakeGUIMainLib + PUBLIC + CMakeGUILib + CMakeGUIQRCLib + $<TARGET_NAME_IF_EXISTS:CMakeVersion> + ) -add_executable(cmake-gui WIN32 MACOSX_BUNDLE CMakeGUIExec.cxx ${MANIFEST_FILE}) -target_link_libraries(cmake-gui CMakeGUIMainLib Qt${INSTALLED_QT_VERSION}::Core) +add_executable(cmake-gui WIN32 MACOSX_BUNDLE CMakeGUIExec.cxx) +target_link_libraries(cmake-gui CMakeGUIMainLib ManifestLib Qt${INSTALLED_QT_VERSION}::Core) -target_sources(CMakeGUIMainLib INTERFACE $<TARGET_OBJECTS:CMakeGUIQRCLib>) if(WIN32) - target_sources(CMakeGUIMainLib INTERFACE $<TARGET_OBJECTS:CMakeVersion> CMakeSetup.rc) + target_sources(CMakeGUIMainLib INTERFACE CMakeSetup.rc) endif() if(APPLE) target_sources(CMakeGUIMainLib INTERFACE CMakeSetup.icns) @@ -300,21 +314,19 @@ if(APPLE) $<TARGET_FILE_DIR:cmake>/cmake-gui ) endif() -set(CMAKE_INSTALL_DESTINATION_ARGS - BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" ${COMPONENT}) install(TARGETS cmake-gui RUNTIME DESTINATION bin ${COMPONENT} - ${CMAKE_INSTALL_DESTINATION_ARGS}) + BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}" ${COMPONENT}) if(UNIX AND NOT APPLE) - foreach (size IN ITEMS 32 128) + foreach(size IN ITEMS 32 128) install( FILES "${CMAKE_CURRENT_SOURCE_DIR}/CMakeSetup${size}.png" DESTINATION "${CMAKE_XDGDATA_DIR}/icons/hicolor/${size}x${size}/apps" ${COMPONENT} RENAME "CMakeSetup.png") - endforeach () + endforeach() # install a desktop file so CMake appears in the application start menu # with an icon @@ -348,5 +360,4 @@ if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32)) endif() set(CMAKE_PACKAGE_QTGUI TRUE) -configure_file("${QtDialog_SOURCE_DIR}/QtDialogCPack.cmake.in" - "${QtDialog_BINARY_DIR}/QtDialogCPack.cmake" @ONLY) +configure_file(QtDialogCPack.cmake.in QtDialogCPack.cmake @ONLY) diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx index f3c4a8b..707eaae 100644 --- a/Source/QtDialog/FirstConfigure.cxx +++ b/Source/QtDialog/FirstConfigure.cxx @@ -244,7 +244,8 @@ void StartCompilerSetup::onGeneratorChanged(int index) if (!DefaultGeneratorPlatform.isEmpty()) { int platform_index = platforms.indexOf(DefaultGeneratorPlatform); if (platform_index != -1) { - this->PlatformOptions->setCurrentIndex(platform_index); + // The index is off-by-one due to the first empty item added above. + this->PlatformOptions->setCurrentIndex(platform_index + 1); } } } else { diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx index 83d6306..6a2ab0b 100644 --- a/Source/cmAddSubDirectoryCommand.cxx +++ b/Source/cmAddSubDirectoryCommand.cxx @@ -26,6 +26,7 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, std::string binArg; bool excludeFromAll = false; + bool system = false; // process the rest of the arguments looking for optional args for (std::string const& arg : cmMakeRange(args).advance(1)) { @@ -33,6 +34,10 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, excludeFromAll = true; continue; } + if (arg == "SYSTEM") { + system = true; + continue; + } if (binArg.empty()) { binArg = arg; } else { @@ -40,6 +45,11 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, return false; } } + // "SYSTEM" directory property should also affects targets in nested + // subdirectories. + if (mf.GetPropertyAsBool("SYSTEM")) { + system = true; + } // Compute the full path to the specified source directory. // Interpret a relative path with respect to the current source directory. @@ -102,7 +112,7 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args, binPath = cmSystemTools::CollapseFullPath(binPath); // Add the subdirectory using the computed full paths. - mf.AddSubDirectory(srcPath, binPath, excludeFromAll, true); + mf.AddSubDirectory(srcPath, binPath, excludeFromAll, true, system); return true; } diff --git a/Source/cmArgumentParser.cxx b/Source/cmArgumentParser.cxx index 4624f1c..ad57a88 100644 --- a/Source/cmArgumentParser.cxx +++ b/Source/cmArgumentParser.cxx @@ -4,9 +4,14 @@ #include <algorithm> +#include "cmArgumentParserTypes.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmStringAlgorithms.h" + namespace ArgumentParser { -auto ActionMap::Emplace(cm::string_view name, Action action) +auto KeywordActionMap::Emplace(cm::string_view name, KeywordAction action) -> std::pair<iterator, bool> { auto const it = @@ -19,7 +24,7 @@ auto ActionMap::Emplace(cm::string_view name, Action action) : std::make_pair(this->emplace(it, name, std::move(action)), true); } -auto ActionMap::Find(cm::string_view name) const -> const_iterator +auto KeywordActionMap::Find(cm::string_view name) const -> const_iterator { auto const it = std::lower_bound(this->begin(), this->end(), name, @@ -29,68 +34,171 @@ auto ActionMap::Find(cm::string_view name) const -> const_iterator return (it != this->end() && it->first == name) ? it : this->end(); } +auto PositionActionMap::Emplace(std::size_t pos, PositionAction action) + -> std::pair<iterator, bool> +{ + auto const it = std::lower_bound( + this->begin(), this->end(), pos, + [](value_type const& elem, std::size_t k) { return elem.first < k; }); + return (it != this->end() && it->first == pos) + ? std::make_pair(it, false) + : std::make_pair(this->emplace(it, pos, std::move(action)), true); +} + +auto PositionActionMap::Find(std::size_t pos) const -> const_iterator +{ + auto const it = std::lower_bound( + this->begin(), this->end(), pos, + [](value_type const& elem, std::size_t k) { return elem.first < k; }); + return (it != this->end() && it->first == pos) ? it : this->end(); +} + +void Instance::Bind(std::function<Continue(cm::string_view)> f, + ExpectAtLeast expect) +{ + this->KeywordValueFunc = std::move(f); + this->KeywordValuesExpected = expect.Count; +} + void Instance::Bind(bool& val) { val = true; - this->CurrentString = nullptr; - this->CurrentList = nullptr; - this->ExpectValue = false; + this->Bind(nullptr, ExpectAtLeast{ 0 }); } void Instance::Bind(std::string& val) { - this->CurrentString = &val; - this->CurrentList = nullptr; - this->ExpectValue = true; + this->Bind( + [&val](cm::string_view arg) -> Continue { + val = std::string(arg); + return Continue::No; + }, + ExpectAtLeast{ 1 }); +} + +void Instance::Bind(NonEmpty<std::string>& val) +{ + this->Bind( + [this, &val](cm::string_view arg) -> Continue { + if (arg.empty() && this->ParseResults) { + this->ParseResults->AddKeywordError(this->Keyword, + " empty string not allowed\n"); + } + val.assign(std::string(arg)); + return Continue::No; + }, + ExpectAtLeast{ 1 }); } -void Instance::Bind(StringList& val) +void Instance::Bind(Maybe<std::string>& val) { - this->CurrentString = nullptr; - this->CurrentList = &val; - this->ExpectValue = true; + this->Bind( + [&val](cm::string_view arg) -> Continue { + static_cast<std::string&>(val) = std::string(arg); + return Continue::No; + }, + ExpectAtLeast{ 0 }); } -void Instance::Bind(MultiStringList& val) +void Instance::Bind(MaybeEmpty<std::vector<std::string>>& val) { - this->CurrentString = nullptr; - this->CurrentList = (static_cast<void>(val.emplace_back()), &val.back()); - this->ExpectValue = false; + this->Bind( + [&val](cm::string_view arg) -> Continue { + val.emplace_back(arg); + return Continue::Yes; + }, + ExpectAtLeast{ 0 }); } -void Instance::Consume(cm::string_view arg, void* result, - std::vector<std::string>* unparsedArguments, - std::vector<std::string>* keywordsMissingValue, - std::vector<std::string>* parsedKeywords) +void Instance::Bind(NonEmpty<std::vector<std::string>>& val) { - auto const it = this->Bindings.Find(arg); - if (it != this->Bindings.end()) { - if (parsedKeywords != nullptr) { - parsedKeywords->emplace_back(arg); + this->Bind( + [&val](cm::string_view arg) -> Continue { + val.emplace_back(arg); + return Continue::Yes; + }, + ExpectAtLeast{ 1 }); +} + +void Instance::Bind(std::vector<std::vector<std::string>>& multiVal) +{ + multiVal.emplace_back(); + std::vector<std::string>& val = multiVal.back(); + this->Bind( + [&val](cm::string_view arg) -> Continue { + val.emplace_back(arg); + return Continue::Yes; + }, + ExpectAtLeast{ 0 }); +} + +void Instance::Consume(std::size_t pos, cm::string_view arg) +{ + auto const it = this->Bindings.Keywords.Find(arg); + if (it != this->Bindings.Keywords.end()) { + this->FinishKeyword(); + this->Keyword = it->first; + this->KeywordValuesSeen = 0; + this->DoneWithPositional = true; + if (this->Bindings.ParsedKeyword) { + this->Bindings.ParsedKeyword(*this, it->first); } - it->second(*this, result); - if (this->ExpectValue && keywordsMissingValue != nullptr) { - keywordsMissingValue->emplace_back(arg); + it->second(*this); + return; + } + + if (this->KeywordValueFunc) { + switch (this->KeywordValueFunc(arg)) { + case Continue::Yes: + break; + case Continue::No: + this->KeywordValueFunc = nullptr; + break; } + ++this->KeywordValuesSeen; return; } - if (this->CurrentString != nullptr) { - this->CurrentString->assign(std::string(arg)); - this->CurrentString = nullptr; - this->CurrentList = nullptr; - } else if (this->CurrentList != nullptr) { - this->CurrentList->emplace_back(arg); - } else if (unparsedArguments != nullptr) { - unparsedArguments->emplace_back(arg); + if (!this->DoneWithPositional) { + auto const pit = this->Bindings.Positions.Find(pos); + if (pit != this->Bindings.Positions.end()) { + pit->second(*this, pos, arg); + return; + } + } + + if (this->UnparsedArguments != nullptr) { + this->UnparsedArguments->emplace_back(arg); } +} - if (this->ExpectValue) { - if (keywordsMissingValue != nullptr) { - keywordsMissingValue->pop_back(); +void Instance::FinishKeyword() +{ + if (this->Keyword.empty()) { + return; + } + if (this->KeywordValuesSeen < this->KeywordValuesExpected) { + if (this->ParseResults != nullptr) { + this->ParseResults->AddKeywordError(this->Keyword, + " missing required value\n"); } - this->ExpectValue = false; + if (this->Bindings.KeywordMissingValue) { + this->Bindings.KeywordMissingValue(*this, this->Keyword); + } + } +} + +bool ParseResult::MaybeReportError(cmMakefile& mf) const +{ + if (*this) { + return false; + } + std::string e; + for (auto const& ke : this->KeywordErrors) { + e = cmStrCat(e, "Error after keyword \"", ke.first, "\":\n", ke.second); } + mf.IssueMessage(MessageType::FATAL_ERROR, e); + return true; } } // namespace ArgumentParser diff --git a/Source/cmArgumentParser.h b/Source/cmArgumentParser.h index 71ed844..fdf54fb 100644 --- a/Source/cmArgumentParser.h +++ b/Source/cmArgumentParser.h @@ -5,59 +5,220 @@ #include "cmConfigure.h" // IWYU pragma: keep #include <cassert> +#include <cstddef> #include <functional> +#include <map> #include <string> #include <utility> #include <vector> +#include <cm/optional> #include <cm/string_view> +#include <cm/type_traits> #include <cmext/string_view> +#include "cmArgumentParserTypes.h" // IWYU pragma: keep + +template <typename Result> +class cmArgumentParser; // IWYU pragma: keep + +class cmMakefile; + namespace ArgumentParser { -using StringList = std::vector<std::string>; -using MultiStringList = std::vector<StringList>; +class ParseResult +{ + std::map<cm::string_view, std::string> KeywordErrors; + +public: + explicit operator bool() const { return this->KeywordErrors.empty(); } + + void AddKeywordError(cm::string_view key, cm::string_view text) + + { + this->KeywordErrors[key] += text; + } + + std::map<cm::string_view, std::string> const& GetKeywordErrors() const + { + return this->KeywordErrors; + } + + bool MaybeReportError(cmMakefile& mf) const; +}; + +template <typename Result> +typename std::enable_if<std::is_base_of<ParseResult, Result>::value, + ParseResult*>::type +AsParseResultPtr(Result& result) +{ + return &result; +} + +template <typename Result> +typename std::enable_if<!std::is_base_of<ParseResult, Result>::value, + ParseResult*>::type +AsParseResultPtr(Result&) +{ + return nullptr; +} + +enum class Continue +{ + No, + Yes, +}; + +struct ExpectAtLeast +{ + std::size_t Count = 0; + + ExpectAtLeast(std::size_t count) + : Count(count) + { + } +}; class Instance; -using Action = std::function<void(Instance&, void*)>; +using KeywordAction = std::function<void(Instance&)>; +using KeywordNameAction = std::function<void(Instance&, cm::string_view)>; +using PositionAction = + std::function<void(Instance&, std::size_t, cm::string_view)>; -// using ActionMap = cm::flat_map<cm::string_view, Action>; -class ActionMap : public std::vector<std::pair<cm::string_view, Action>> +// using KeywordActionMap = cm::flat_map<cm::string_view, KeywordAction>; +class KeywordActionMap + : public std::vector<std::pair<cm::string_view, KeywordAction>> { public: - std::pair<iterator, bool> Emplace(cm::string_view name, Action action); + std::pair<iterator, bool> Emplace(cm::string_view name, + KeywordAction action); const_iterator Find(cm::string_view name) const; }; +// using PositionActionMap = cm::flat_map<cm::string_view, PositionAction>; +class PositionActionMap + : public std::vector<std::pair<std::size_t, PositionAction>> +{ +public: + std::pair<iterator, bool> Emplace(std::size_t pos, PositionAction action); + const_iterator Find(std::size_t pos) const; +}; + +class ActionMap +{ +public: + KeywordActionMap Keywords; + KeywordNameAction KeywordMissingValue; + KeywordNameAction ParsedKeyword; + PositionActionMap Positions; +}; + +class Base +{ +public: + using ExpectAtLeast = ArgumentParser::ExpectAtLeast; + using Continue = ArgumentParser::Continue; + using Instance = ArgumentParser::Instance; + using ParseResult = ArgumentParser::ParseResult; + + ArgumentParser::ActionMap Bindings; + + bool MaybeBind(cm::string_view name, KeywordAction action) + { + return this->Bindings.Keywords.Emplace(name, std::move(action)).second; + } + + void Bind(cm::string_view name, KeywordAction action) + { + bool const inserted = this->MaybeBind(name, std::move(action)); + assert(inserted); + static_cast<void>(inserted); + } + + void BindParsedKeyword(KeywordNameAction action) + { + assert(!this->Bindings.ParsedKeyword); + this->Bindings.ParsedKeyword = std::move(action); + } + + void BindKeywordMissingValue(KeywordNameAction action) + { + assert(!this->Bindings.KeywordMissingValue); + this->Bindings.KeywordMissingValue = std::move(action); + } + + void Bind(std::size_t pos, PositionAction action) + { + bool const inserted = + this->Bindings.Positions.Emplace(pos, std::move(action)).second; + assert(inserted); + static_cast<void>(inserted); + } +}; + class Instance { public: - Instance(ActionMap const& bindings) + Instance(ActionMap const& bindings, ParseResult* parseResult, + std::vector<std::string>* unparsedArguments, void* result = nullptr) : Bindings(bindings) + , ParseResults(parseResult) + , UnparsedArguments(unparsedArguments) + , Result(result) { } + void Bind(std::function<Continue(cm::string_view)> f, ExpectAtLeast expect); void Bind(bool& val); void Bind(std::string& val); - void Bind(StringList& val); - void Bind(MultiStringList& val); + void Bind(NonEmpty<std::string>& val); + void Bind(Maybe<std::string>& val); + void Bind(MaybeEmpty<std::vector<std::string>>& val); + void Bind(NonEmpty<std::vector<std::string>>& val); + void Bind(std::vector<std::vector<std::string>>& val); + + // cm::optional<> records the presence the keyword to which it binds. + template <typename T> + void Bind(cm::optional<T>& optVal) + { + if (!optVal) { + optVal.emplace(); + } + this->Bind(*optVal); + } - void Consume(cm::string_view arg, void* result, - std::vector<std::string>* unparsedArguments, - std::vector<std::string>* keywordsMissingValue, - std::vector<std::string>* parsedKeywords); + template <typename Range> + void Parse(Range const& args, std::size_t pos = 0) + { + for (cm::string_view arg : args) { + this->Consume(pos++, arg); + } + this->FinishKeyword(); + } private: ActionMap const& Bindings; - std::string* CurrentString = nullptr; - StringList* CurrentList = nullptr; - bool ExpectValue = false; + ParseResult* ParseResults = nullptr; + std::vector<std::string>* UnparsedArguments = nullptr; + void* Result = nullptr; + + cm::string_view Keyword; + std::size_t KeywordValuesSeen = 0; + std::size_t KeywordValuesExpected = 0; + std::function<Continue(cm::string_view)> KeywordValueFunc; + bool DoneWithPositional = false; + + void Consume(std::size_t pos, cm::string_view arg); + void FinishKeyword(); + + template <typename Result> + friend class ::cmArgumentParser; }; } // namespace ArgumentParser template <typename Result> -class cmArgumentParser +class cmArgumentParser : private ArgumentParser::Base { public: // I *think* this function could be made `constexpr` when the code is @@ -65,83 +226,194 @@ public: template <typename T> cmArgumentParser& Bind(cm::static_string_view name, T Result::*member) { - bool const inserted = - this->Bindings - .Emplace(name, - [member](ArgumentParser::Instance& instance, void* result) { - instance.Bind(static_cast<Result*>(result)->*member); - }) - .second; - assert(inserted), (void)inserted; + this->Base::Bind(name, [member](Instance& instance) { + instance.Bind(static_cast<Result*>(instance.Result)->*member); + }); + return *this; + } + + cmArgumentParser& Bind(cm::static_string_view name, + Continue (Result::*member)(cm::string_view), + ExpectAtLeast expect = { 1 }) + { + this->Base::Bind(name, [member, expect](Instance& instance) { + Result* result = static_cast<Result*>(instance.Result); + instance.Bind( + [result, member](cm::string_view arg) -> Continue { + return (result->*member)(arg); + }, + expect); + }); + return *this; + } + + cmArgumentParser& Bind(cm::static_string_view name, + Continue (Result::*member)(cm::string_view, + cm::string_view), + ExpectAtLeast expect = { 1 }) + { + this->Base::Bind(name, [member, expect](Instance& instance) { + Result* result = static_cast<Result*>(instance.Result); + cm::string_view keyword = instance.Keyword; + instance.Bind( + [result, member, keyword](cm::string_view arg) -> Continue { + return (result->*member)(keyword, arg); + }, + expect); + }); + return *this; + } + + cmArgumentParser& Bind(cm::static_string_view name, + std::function<Continue(Result&, cm::string_view)> f, + ExpectAtLeast expect = { 1 }) + { + this->Base::Bind(name, [f, expect](Instance& instance) { + Result* result = static_cast<Result*>(instance.Result); + instance.Bind( + [result, &f](cm::string_view arg) -> Continue { + return f(*result, arg); + }, + expect); + }); + return *this; + } + + cmArgumentParser& Bind( + cm::static_string_view name, + std::function<Continue(Result&, cm::string_view, cm::string_view)> f, + ExpectAtLeast expect = { 1 }) + { + this->Base::Bind(name, [f, expect](Instance& instance) { + Result* result = static_cast<Result*>(instance.Result); + cm::string_view keyword = instance.Keyword; + instance.Bind( + [result, keyword, &f](cm::string_view arg) -> Continue { + return f(*result, keyword, arg); + }, + expect); + }); + return *this; + } + + cmArgumentParser& Bind(std::size_t position, + cm::optional<std::string> Result::*member) + { + this->Base::Bind( + position, + [member](Instance& instance, std::size_t, cm::string_view arg) { + Result* result = static_cast<Result*>(instance.Result); + result->*member = arg; + }); + return *this; + } + + cmArgumentParser& BindParsedKeywords( + std::vector<cm::string_view> Result::*member) + { + this->Base::BindParsedKeyword( + [member](Instance& instance, cm::string_view arg) { + (static_cast<Result*>(instance.Result)->*member).emplace_back(arg); + }); return *this; } template <typename Range> - void Parse(Result& result, Range const& args, - std::vector<std::string>* unparsedArguments = nullptr, - std::vector<std::string>* keywordsMissingValue = nullptr, - std::vector<std::string>* parsedKeywords = nullptr) const + bool Parse(Result& result, Range const& args, + std::vector<std::string>* unparsedArguments, + std::size_t pos = 0) const { - ArgumentParser::Instance instance(this->Bindings); - for (cm::string_view arg : args) { - instance.Consume(arg, &result, unparsedArguments, keywordsMissingValue, - parsedKeywords); - } + using ArgumentParser::AsParseResultPtr; + ParseResult* parseResultPtr = AsParseResultPtr(result); + Instance instance(this->Bindings, parseResultPtr, unparsedArguments, + &result); + instance.Parse(args, pos); + return parseResultPtr ? static_cast<bool>(*parseResultPtr) : true; } template <typename Range> - Result Parse(Range const& args, - std::vector<std::string>* unparsedArguments = nullptr, - std::vector<std::string>* keywordsMissingValue = nullptr, - std::vector<std::string>* parsedKeywords = nullptr) const + Result Parse(Range const& args, std::vector<std::string>* unparsedArguments, + std::size_t pos = 0) const { Result result; - this->Parse(result, args, unparsedArguments, keywordsMissingValue, - parsedKeywords); + this->Parse(result, args, unparsedArguments, pos); return result; } - -private: - ArgumentParser::ActionMap Bindings; }; template <> -class cmArgumentParser<void> +class cmArgumentParser<void> : private ArgumentParser::Base { public: template <typename T> cmArgumentParser& Bind(cm::static_string_view name, T& ref) { - bool const inserted = this->Bind(cm::string_view(name), ref); - assert(inserted), (void)inserted; + this->Base::Bind(name, [&ref](Instance& instance) { instance.Bind(ref); }); + return *this; + } + + cmArgumentParser& Bind(cm::static_string_view name, + std::function<Continue(cm::string_view)> f, + ExpectAtLeast expect = { 1 }) + { + this->Base::Bind(name, [f, expect](Instance& instance) { + instance.Bind([&f](cm::string_view arg) -> Continue { return f(arg); }, + expect); + }); + return *this; + } + + cmArgumentParser& Bind( + cm::static_string_view name, + std::function<Continue(cm::string_view, cm::string_view)> f, + ExpectAtLeast expect = { 1 }) + { + this->Base::Bind(name, [f, expect](Instance& instance) { + cm::string_view keyword = instance.Keyword; + instance.Bind( + [keyword, &f](cm::string_view arg) -> Continue { + return f(keyword, arg); + }, + expect); + }); + return *this; + } + + cmArgumentParser& Bind(std::size_t position, cm::optional<std::string>& ref) + { + this->Base::Bind(position, + [&ref](Instance&, std::size_t, cm::string_view arg) { + ref = std::string(arg); + }); + return *this; + } + + cmArgumentParser& BindParsedKeywords(std::vector<cm::string_view>& ref) + { + this->Base::BindParsedKeyword( + [&ref](Instance&, cm::string_view arg) { ref.emplace_back(arg); }); return *this; } template <typename Range> - void Parse(Range const& args, - std::vector<std::string>* unparsedArguments = nullptr, - std::vector<std::string>* keywordsMissingValue = nullptr, - std::vector<std::string>* parsedKeywords = nullptr) const + ParseResult Parse(Range const& args, + std::vector<std::string>* unparsedArguments, + std::size_t pos = 0) const { - ArgumentParser::Instance instance(this->Bindings); - for (cm::string_view arg : args) { - instance.Consume(arg, nullptr, unparsedArguments, keywordsMissingValue, - parsedKeywords); - } + ParseResult parseResult; + Instance instance(this->Bindings, &parseResult, unparsedArguments); + instance.Parse(args, pos); + return parseResult; } protected: + using Base::Instance; + using Base::BindKeywordMissingValue; + template <typename T> bool Bind(cm::string_view name, T& ref) { - return this->Bindings - .Emplace(name, - [&ref](ArgumentParser::Instance& instance, void*) { - instance.Bind(ref); - }) - .second; + return this->MaybeBind(name, + [&ref](Instance& instance) { instance.Bind(ref); }); } - -private: - ArgumentParser::ActionMap Bindings; }; diff --git a/Source/cmArgumentParserTypes.h b/Source/cmArgumentParserTypes.h new file mode 100644 index 0000000..7daae09 --- /dev/null +++ b/Source/cmArgumentParserTypes.h @@ -0,0 +1,69 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#if defined(__SUNPRO_CC) + +# include <string> +# include <vector> + +namespace ArgumentParser { + +template <typename T> +struct Maybe; +template <> +struct Maybe<std::string> : public std::string +{ + using std::string::basic_string; +}; + +template <typename T> +struct MaybeEmpty; +template <typename T> +struct MaybeEmpty<std::vector<T>> : public std::vector<T> +{ + using std::vector<T>::vector; +}; + +template <typename T> +struct NonEmpty; +template <typename T> +struct NonEmpty<std::vector<T>> : public std::vector<T> +{ + using std::vector<T>::vector; +}; +template <> +struct NonEmpty<std::string> : public std::string +{ + using std::string::basic_string; +}; + +} // namespace ArgumentParser + +#else + +namespace ArgumentParser { + +template <typename T> +struct Maybe : public T +{ + using T::T; +}; + +template <typename T> +struct MaybeEmpty : public T +{ + using T::T; +}; + +template <typename T> +struct NonEmpty : public T +{ + using T::T; +}; + +} // namespace ArgumentParser + +#endif diff --git a/Source/cmBlockCommand.cxx b/Source/cmBlockCommand.cxx new file mode 100644 index 0000000..ec79149 --- /dev/null +++ b/Source/cmBlockCommand.cxx @@ -0,0 +1,197 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmBlockCommand.h" + +#include <cstdint> // IWYU pragma: keep +#include <utility> + +#include <cm/memory> +#include <cm/optional> +#include <cm/string_view> +#include <cmext/enum_set> +#include <cmext/string_view> + +#include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" +#include "cmExecutionStatus.h" +#include "cmFunctionBlocker.h" +#include "cmListFileCache.h" +#include "cmMakefile.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +namespace { +enum class ScopeType : std::uint8_t +{ + VARIABLES, + POLICIES +}; +using ScopeSet = cm::enum_set<ScopeType>; + +class BlockScopePushPop +{ +public: + BlockScopePushPop(cmMakefile* m, const ScopeSet& scopes); + ~BlockScopePushPop() = default; + + BlockScopePushPop(const BlockScopePushPop&) = delete; + BlockScopePushPop& operator=(const BlockScopePushPop&) = delete; + +private: + std::unique_ptr<cmMakefile::PolicyPushPop> PolicyScope; + std::unique_ptr<cmMakefile::VariablePushPop> VariableScope; +}; + +BlockScopePushPop::BlockScopePushPop(cmMakefile* mf, const ScopeSet& scopes) +{ + if (scopes.contains(ScopeType::POLICIES)) { + this->PolicyScope = cm::make_unique<cmMakefile::PolicyPushPop>(mf); + } + if (scopes.contains(ScopeType::VARIABLES)) { + this->VariableScope = cm::make_unique<cmMakefile::VariablePushPop>(mf); + } +} + +class cmBlockFunctionBlocker : public cmFunctionBlocker +{ +public: + cmBlockFunctionBlocker(cmMakefile* mf, const ScopeSet& scopes, + std::vector<std::string> variableNames); + ~cmBlockFunctionBlocker() override; + + cm::string_view StartCommandName() const override { return "block"_s; } + cm::string_view EndCommandName() const override { return "endblock"_s; } + + bool EndCommandSupportsArguments() const override { return false; } + + bool ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile& mf) const override; + + bool Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) override; + +private: + cmMakefile* Makefile; + ScopeSet Scopes; + BlockScopePushPop BlockScope; + std::vector<std::string> VariableNames; +}; + +cmBlockFunctionBlocker::cmBlockFunctionBlocker( + cmMakefile* const mf, const ScopeSet& scopes, + std::vector<std::string> variableNames) + : Makefile{ mf } + , Scopes{ scopes } + , BlockScope{ mf, scopes } + , VariableNames{ std::move(variableNames) } +{ +} + +cmBlockFunctionBlocker::~cmBlockFunctionBlocker() +{ + if (this->Scopes.contains(ScopeType::VARIABLES)) { + this->Makefile->RaiseScope(this->VariableNames); + } +} + +bool cmBlockFunctionBlocker::ArgumentsMatch(cmListFileFunction const& lff, + cmMakefile&) const +{ + // no arguments expected for endblock() + // but this method should not be called because EndCommandHasArguments() + // returns false. + return lff.Arguments().empty(); +} + +bool cmBlockFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, + cmExecutionStatus& inStatus) +{ + auto& mf = inStatus.GetMakefile(); + + // Invoke all the functions that were collected in the block. + for (cmListFileFunction const& fn : functions) { + cmExecutionStatus status(mf); + mf.ExecuteCommand(fn, status); + if (status.GetReturnInvoked()) { + mf.RaiseScope(status.GetReturnVariables()); + inStatus.SetReturnInvoked(status.GetReturnVariables()); + return true; + } + if (status.GetBreakInvoked()) { + inStatus.SetBreakInvoked(); + return true; + } + if (status.GetContinueInvoked()) { + inStatus.SetContinueInvoked(); + return true; + } + if (cmSystemTools::GetFatalErrorOccurred()) { + return true; + } + } + return true; +} + +} // anonymous namespace + +bool cmBlockCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + struct Arguments : public ArgumentParser::ParseResult + { + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> ScopeFor; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Propagate; + }; + static auto const parser = cmArgumentParser<Arguments>{} + .Bind("SCOPE_FOR"_s, &Arguments::ScopeFor) + .Bind("PROPAGATE"_s, &Arguments::Propagate); + std::vector<std::string> unrecognizedArguments; + auto parsedArgs = parser.Parse(args, &unrecognizedArguments); + + if (!unrecognizedArguments.empty()) { + status.SetError(cmStrCat("called with unsupported argument \"", + unrecognizedArguments[0], '"')); + cmSystemTools::SetFatalErrorOccurred(); + return false; + } + + if (parsedArgs.MaybeReportError(status.GetMakefile())) { + cmSystemTools::SetFatalErrorOccurred(); + return true; + } + + ScopeSet scopes; + + if (parsedArgs.ScopeFor) { + for (auto const& scope : *parsedArgs.ScopeFor) { + if (scope == "VARIABLES"_s) { + scopes.insert(ScopeType::VARIABLES); + continue; + } + if (scope == "POLICIES"_s) { + scopes.insert(ScopeType::POLICIES); + continue; + } + status.SetError(cmStrCat("SCOPE_FOR unsupported scope \"", scope, '"')); + cmSystemTools::SetFatalErrorOccurred(); + return false; + } + } else { + scopes = { ScopeType::VARIABLES, ScopeType::POLICIES }; + } + if (!scopes.contains(ScopeType::VARIABLES) && + !parsedArgs.Propagate.empty()) { + status.SetError( + "PROPAGATE cannot be specified without a new scope for VARIABLES"); + cmSystemTools::SetFatalErrorOccurred(); + return false; + } + + // create a function blocker + auto fb = cm::make_unique<cmBlockFunctionBlocker>( + &status.GetMakefile(), scopes, parsedArgs.Propagate); + status.GetMakefile().AddFunctionBlocker(std::move(fb)); + + return true; +} diff --git a/Source/cmBlockCommand.h b/Source/cmBlockCommand.h new file mode 100644 index 0000000..5fd8f42 --- /dev/null +++ b/Source/cmBlockCommand.h @@ -0,0 +1,14 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <string> +#include <vector> + +class cmExecutionStatus; + +/// Starts block() ... endblock() block +bool cmBlockCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx index 0750eea..58129a0 100644 --- a/Source/cmCMakeHostSystemInformationCommand.cxx +++ b/Source/cmCMakeHostSystemInformationCommand.cxx @@ -474,7 +474,7 @@ bool QueryWindowsRegistry(Range args, cmExecutionStatus& status, } std::string const& key = *args.begin(); - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { std::string ValueName; bool ValueNames = false; @@ -491,19 +491,15 @@ bool QueryWindowsRegistry(Range args, cmExecutionStatus& status, .Bind("SEPARATOR"_s, &Arguments::Separator) .Bind("ERROR_VARIABLE"_s, &Arguments::ErrorVariable); std::vector<std::string> invalidArgs; - std::vector<std::string> keywordsMissingValue; - Arguments const arguments = - parser.Parse(args.advance(1), &invalidArgs, &keywordsMissingValue); + Arguments const arguments = parser.Parse(args.advance(1), &invalidArgs); if (!invalidArgs.empty()) { status.SetError(cmStrCat("given invalid argument(s) \"", cmJoin(invalidArgs, ", "_s), "\".")); return false; } - if (!keywordsMissingValue.empty()) { - status.SetError(cmStrCat("missing expected value for argument(s) \"", - cmJoin(keywordsMissingValue, ", "_s), "\".")); - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } if ((!arguments.ValueName.empty() && (arguments.ValueNames || arguments.SubKeys)) || diff --git a/Source/cmCMakeLanguageCommand.cxx b/Source/cmCMakeLanguageCommand.cxx index a2aaa2a..68e658c 100644 --- a/Source/cmCMakeLanguageCommand.cxx +++ b/Source/cmCMakeLanguageCommand.cxx @@ -14,15 +14,18 @@ #include <cmext/string_view> #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" #include "cmDependencyProvider.h" #include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmListFileCache.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmRange.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmake.h" namespace { @@ -33,13 +36,14 @@ bool FatalError(cmExecutionStatus& status, std::string const& error) return false; } -std::array<cm::static_string_view, 12> InvalidCommands{ +std::array<cm::static_string_view, 14> InvalidCommands{ { // clang-format off "function"_s, "endfunction"_s, "macro"_s, "endmacro"_s, "if"_s, "elseif"_s, "else"_s, "endif"_s, "while"_s, "endwhile"_s, - "foreach"_s, "endforeach"_s + "foreach"_s, "endforeach"_s, + "block"_s, "endblock"_s } // clang-format on }; @@ -235,7 +239,7 @@ bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER( struct SetProviderArgs { std::string Command; - std::vector<std::string> Methods; + ArgumentParser::NonEmpty<std::vector<std::string>> Methods; }; auto const ArgsParser = @@ -303,6 +307,27 @@ bool cmCMakeLanguageCommandSET_DEPENDENCY_PROVIDER( return true; } + +bool cmCMakeLanguageCommandGET_MESSAGE_LOG_LEVEL( + std::vector<cmListFileArgument> const& args, cmExecutionStatus& status) +{ + cmMakefile& makefile = status.GetMakefile(); + std::vector<std::string> expandedArgs; + makefile.ExpandArguments(args, expandedArgs); + + if (args.size() < 2 || expandedArgs.size() > 2) { + return FatalError( + status, + "sub-command GET_MESSAGE_LOG_LEVEL expects exactly one argument"); + } + + Message::LogLevel logLevel = makefile.GetCurrentLogLevel(); + std::string outputValue = cmake::LogLevelToString(logLevel); + + const std::string& outputVariable = expandedArgs[1]; + makefile.AddDefinition(outputVariable, outputValue); + return true; +} } bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args, @@ -451,5 +476,9 @@ bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args, return cmCMakeLanguageCommandEVAL(args, status); } + if (expArgs[expArg] == "GET_MESSAGE_LOG_LEVEL") { + return cmCMakeLanguageCommandGET_MESSAGE_LOG_LEVEL(args, status); + } + return FatalError(status, "called with unknown meta-operation"); } diff --git a/Source/cmCMakePathCommand.cxx b/Source/cmCMakePathCommand.cxx index bf94c2d..7755082 100644 --- a/Source/cmCMakePathCommand.cxx +++ b/Source/cmCMakePathCommand.cxx @@ -2,7 +2,6 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCMakePathCommand.h" -#include <algorithm> #include <functional> #include <iomanip> #include <map> @@ -11,10 +10,12 @@ #include <utility> #include <vector> +#include <cm/optional> #include <cm/string_view> #include <cmext/string_view> #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" #include "cmCMakePath.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" @@ -43,15 +44,12 @@ public: } template <int Advance = 2> - Result Parse(std::vector<std::string> const& args, - std::vector<std::string>* keywordsMissingValue = nullptr, - std::vector<std::string>* parsedKeywords = nullptr) const + Result Parse(std::vector<std::string> const& args) const { this->Inputs.clear(); return this->cmArgumentParser<Result>::Parse( - cmMakeRange(args).advance(Advance), &this->Inputs, keywordsMissingValue, - parsedKeywords); + cmMakeRange(args).advance(Advance), &this->Inputs); } const std::vector<std::string>& GetInputs() const { return this->Inputs; } @@ -82,52 +80,14 @@ public: template <int Advance = 2> Result Parse(std::vector<std::string> const& args) const { - this->KeywordsMissingValue.clear(); - this->ParsedKeywords.clear(); - return this->CMakePathArgumentParser<Result>::template Parse<Advance>( - args, &this->KeywordsMissingValue, &this->ParsedKeywords); - } - - const std::vector<std::string>& GetKeywordsMissingValue() const - { - return this->KeywordsMissingValue; - } - const std::vector<std::string>& GetParsedKeywords() const - { - return this->ParsedKeywords; - } - - bool checkOutputVariable(const Result& arguments, - cmExecutionStatus& status) const - { - if (std::find(this->GetKeywordsMissingValue().begin(), - this->GetKeywordsMissingValue().end(), - "OUTPUT_VARIABLE"_s) != - this->GetKeywordsMissingValue().end()) { - status.SetError("OUTPUT_VARIABLE requires an argument."); - return false; - } - - if (std::find(this->GetParsedKeywords().begin(), - this->GetParsedKeywords().end(), - "OUTPUT_VARIABLE"_s) != this->GetParsedKeywords().end() && - arguments.Output.empty()) { - status.SetError("Invalid name for output variable."); - return false; - } - - return true; + args); } - -private: - mutable std::vector<std::string> KeywordsMissingValue; - mutable std::vector<std::string> ParsedKeywords; }; -struct OutputVariable +struct OutputVariable : public ArgumentParser::ParseResult { - std::string Output; + cm::optional<ArgumentParser::NonEmpty<std::string>> Output; }; // Usable when OUTPUT_VARIABLE is the only option class OutputVariableParser @@ -297,8 +257,8 @@ bool HandleAppendCommand(std::vector<std::string> const& args, const auto arguments = parser.Parse(args); - if (!parser.checkOutputVariable(arguments, status)) { - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } cmCMakePath path(status.GetMakefile().GetSafeDefinition(args[1])); @@ -307,7 +267,7 @@ bool HandleAppendCommand(std::vector<std::string> const& args, } status.GetMakefile().AddDefinition( - arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + arguments.Output ? *arguments.Output : args[1], path.String()); return true; } @@ -319,8 +279,8 @@ bool HandleAppendStringCommand(std::vector<std::string> const& args, const auto arguments = parser.Parse(args); - if (!parser.checkOutputVariable(arguments, status)) { - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } std::string inputPath; @@ -334,7 +294,7 @@ bool HandleAppendStringCommand(std::vector<std::string> const& args, } status.GetMakefile().AddDefinition( - arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + arguments.Output ? *arguments.Output : args[1], path.String()); return true; } @@ -346,8 +306,8 @@ bool HandleRemoveFilenameCommand(std::vector<std::string> const& args, const auto arguments = parser.Parse(args); - if (!parser.checkOutputVariable(arguments, status)) { - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } if (!parser.GetInputs().empty()) { @@ -364,7 +324,7 @@ bool HandleRemoveFilenameCommand(std::vector<std::string> const& args, path.RemoveFileName(); status.GetMakefile().AddDefinition( - arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + arguments.Output ? *arguments.Output : args[1], path.String()); return true; } @@ -376,8 +336,8 @@ bool HandleReplaceFilenameCommand(std::vector<std::string> const& args, const auto arguments = parser.Parse(args); - if (!parser.checkOutputVariable(arguments, status)) { - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } if (parser.GetInputs().size() > 1) { @@ -395,7 +355,7 @@ bool HandleReplaceFilenameCommand(std::vector<std::string> const& args, parser.GetInputs().empty() ? "" : parser.GetInputs().front()); status.GetMakefile().AddDefinition( - arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + arguments.Output ? *arguments.Output : args[1], path.String()); return true; } @@ -403,9 +363,9 @@ bool HandleReplaceFilenameCommand(std::vector<std::string> const& args, bool HandleRemoveExtensionCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { - std::string Output; + cm::optional<ArgumentParser::NonEmpty<std::string>> Output; bool LastOnly = false; }; @@ -415,8 +375,8 @@ bool HandleRemoveExtensionCommand(std::vector<std::string> const& args, Arguments const arguments = parser.Parse(args); - if (!parser.checkOutputVariable(arguments, status)) { - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } if (!parser.GetInputs().empty()) { @@ -438,7 +398,7 @@ bool HandleRemoveExtensionCommand(std::vector<std::string> const& args, } status.GetMakefile().AddDefinition( - arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + arguments.Output ? *arguments.Output : args[1], path.String()); return true; } @@ -446,9 +406,9 @@ bool HandleRemoveExtensionCommand(std::vector<std::string> const& args, bool HandleReplaceExtensionCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { - std::string Output; + cm::optional<ArgumentParser::NonEmpty<std::string>> Output; bool LastOnly = false; }; @@ -458,8 +418,8 @@ bool HandleReplaceExtensionCommand(std::vector<std::string> const& args, Arguments const arguments = parser.Parse(args); - if (!parser.checkOutputVariable(arguments, status)) { - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } if (parser.GetInputs().size() > 1) { @@ -483,7 +443,7 @@ bool HandleReplaceExtensionCommand(std::vector<std::string> const& args, } status.GetMakefile().AddDefinition( - arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + arguments.Output ? *arguments.Output : args[1], path.String()); return true; } @@ -495,8 +455,8 @@ bool HandleNormalPathCommand(std::vector<std::string> const& args, const auto arguments = parser.Parse(args); - if (!parser.checkOutputVariable(arguments, status)) { - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } if (!parser.GetInputs().empty()) { @@ -512,7 +472,7 @@ bool HandleNormalPathCommand(std::vector<std::string> const& args, auto path = cmCMakePath(inputPath).Normal(); status.GetMakefile().AddDefinition( - arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + arguments.Output ? *arguments.Output : args[1], path.String()); return true; } @@ -523,10 +483,10 @@ bool HandleTransformPathCommand( const std::string& base)>& transform, bool normalizeOption = false) { - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { - std::string Output; - std::string BaseDirectory; + cm::optional<ArgumentParser::NonEmpty<std::string>> Output; + cm::optional<std::string> BaseDirectory; bool Normalize = false; }; @@ -538,8 +498,8 @@ bool HandleTransformPathCommand( Arguments arguments = parser.Parse(args); - if (!parser.checkOutputVariable(arguments, status)) { - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } if (!parser.GetInputs().empty()) { @@ -547,17 +507,11 @@ bool HandleTransformPathCommand( return false; } - if (std::find(parser.GetKeywordsMissingValue().begin(), - parser.GetKeywordsMissingValue().end(), "BASE_DIRECTORY"_s) != - parser.GetKeywordsMissingValue().end()) { - status.SetError("BASE_DIRECTORY requires an argument."); - return false; - } - - if (std::find(parser.GetParsedKeywords().begin(), - parser.GetParsedKeywords().end(), - "BASE_DIRECTORY"_s) == parser.GetParsedKeywords().end()) { - arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory(); + std::string baseDirectory; + if (arguments.BaseDirectory) { + baseDirectory = *arguments.BaseDirectory; + } else { + baseDirectory = status.GetMakefile().GetCurrentSourceDirectory(); } std::string inputPath; @@ -565,13 +519,13 @@ bool HandleTransformPathCommand( return false; } - auto path = transform(cmCMakePath(inputPath), arguments.BaseDirectory); + auto path = transform(cmCMakePath(inputPath), baseDirectory); if (arguments.Normalize) { path = path.Normal(); } status.GetMakefile().AddDefinition( - arguments.Output.empty() ? args[1] : arguments.Output, path.String()); + arguments.Output ? *arguments.Output : args[1], path.String()); return true; } diff --git a/Source/cmCMakePresetsGraph.cxx b/Source/cmCMakePresetsGraph.cxx index b737c1f..7325e44 100644 --- a/Source/cmCMakePresetsGraph.cxx +++ b/Source/cmCMakePresetsGraph.cxx @@ -43,6 +43,10 @@ using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset; using BuildPreset = cmCMakePresetsGraph::BuildPreset; using TestPreset = cmCMakePresetsGraph::TestPreset; +using PackagePreset = cmCMakePresetsGraph::PackagePreset; +using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset; +template <typename T> +using PresetPair = cmCMakePresetsGraph::PresetPair<T>; using ExpandMacroResult = cmCMakePresetsGraphInternal::ExpandMacroResult; using MacroExpander = cmCMakePresetsGraphInternal::MacroExpander; @@ -261,6 +265,8 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const TestPreset& preset, if (out->Output) { CHECK_EXPAND(out, out->Output->OutputLogFile, macroExpanders, graph.GetVersion(preset)); + CHECK_EXPAND(out, out->Output->OutputJUnitFile, macroExpanders, + graph.GetVersion(preset)); } if (out->Filter) { @@ -301,6 +307,36 @@ bool ExpandMacros(const cmCMakePresetsGraph& graph, const TestPreset& preset, return true; } +bool ExpandMacros(const cmCMakePresetsGraph& graph, + const PackagePreset& preset, + cm::optional<PackagePreset>& out, + const std::vector<MacroExpander>& macroExpanders) +{ + for (auto& variable : out->Variables) { + CHECK_EXPAND(out, variable.second, macroExpanders, + graph.GetVersion(preset)); + } + + CHECK_EXPAND(out, out->ConfigFile, macroExpanders, graph.GetVersion(preset)); + CHECK_EXPAND(out, out->PackageName, macroExpanders, + graph.GetVersion(preset)); + CHECK_EXPAND(out, out->PackageVersion, macroExpanders, + graph.GetVersion(preset)); + CHECK_EXPAND(out, out->PackageDirectory, macroExpanders, + graph.GetVersion(preset)); + CHECK_EXPAND(out, out->VendorName, macroExpanders, graph.GetVersion(preset)); + + return true; +} + +bool ExpandMacros(const cmCMakePresetsGraph& /*graph*/, + const WorkflowPreset& /*preset*/, + cm::optional<WorkflowPreset>& /*out*/, + const std::vector<MacroExpander>& /*macroExpanders*/) +{ + return true; +} + template <class T> bool ExpandMacros(const cmCMakePresetsGraph& graph, const T& preset, cm::optional<T>& out) @@ -556,6 +592,42 @@ ExpandMacroResult ExpandMacro(std::string& out, return ExpandMacroResult::Error; } + +template <typename T> +ReadFileResult SetupWorkflowConfigurePreset( + const T& preset, const ConfigurePreset*& configurePreset) +{ + if (preset.ConfigurePreset != configurePreset->Name) { + return ReadFileResult::INVALID_WORKFLOW_STEPS; + } + return ReadFileResult::READ_OK; +} + +template <> +ReadFileResult SetupWorkflowConfigurePreset<ConfigurePreset>( + const ConfigurePreset& preset, const ConfigurePreset*& configurePreset) +{ + configurePreset = &preset; + return ReadFileResult::READ_OK; +} + +template <typename T> +ReadFileResult TryReachPresetFromWorkflow( + const WorkflowPreset& origin, + const std::map<std::string, PresetPair<T>>& presets, const std::string& name, + const ConfigurePreset*& configurePreset) +{ + auto it = presets.find(name); + if (it == presets.end()) { + return ReadFileResult::INVALID_WORKFLOW_STEPS; + } + if (!origin.OriginFile->ReachableFiles.count( + it->second.Unexpanded.OriginFile)) { + return ReadFileResult::WORKFLOW_STEP_UNREACHABLE_FROM_FILE; + } + return SetupWorkflowConfigurePreset<T>(it->second.Unexpanded, + configurePreset); +} } bool cmCMakePresetsGraphInternal::EqualsCondition::Evaluate( @@ -781,6 +853,7 @@ cmCMakePresetsGraph::TestPreset::VisitPresetInherit( parentOutput.OutputOnFailure); InheritOptionalValue(output.Quiet, parentOutput.Quiet); InheritString(output.OutputLogFile, parentOutput.OutputLogFile); + InheritString(output.OutputJUnitFile, parentOutput.OutputJUnitFile); InheritOptionalValue(output.LabelSummary, parentOutput.LabelSummary); InheritOptionalValue(output.SubprojectSummary, parentOutput.SubprojectSummary); @@ -868,6 +941,57 @@ cmCMakePresetsGraph::TestPreset::VisitPresetAfterInherit(int /* version */) return ReadFileResult::READ_OK; } +cmCMakePresetsGraph::ReadFileResult +cmCMakePresetsGraph::PackagePreset::VisitPresetInherit( + const cmCMakePresetsGraph::Preset& parentPreset) +{ + auto& preset = *this; + const PackagePreset& parent = + static_cast<const PackagePreset&>(parentPreset); + + InheritString(preset.ConfigurePreset, parent.ConfigurePreset); + InheritOptionalValue(preset.InheritConfigureEnvironment, + parent.InheritConfigureEnvironment); + InheritVector(preset.Generators, parent.Generators); + InheritVector(preset.Configurations, parent.Configurations); + + for (auto const& v : parent.Variables) { + preset.Variables.insert(v); + } + + InheritOptionalValue(preset.DebugOutput, parent.DebugOutput); + InheritOptionalValue(preset.VerboseOutput, parent.VerboseOutput); + InheritString(preset.PackageName, parent.PackageName); + InheritString(preset.PackageVersion, parent.PackageVersion); + InheritString(preset.PackageDirectory, parent.PackageDirectory); + InheritString(preset.VendorName, parent.VendorName); + + return ReadFileResult::READ_OK; +} + +cmCMakePresetsGraph::ReadFileResult +cmCMakePresetsGraph::PackagePreset::VisitPresetAfterInherit(int /* version */) +{ + auto& preset = *this; + if (!preset.Hidden && preset.ConfigurePreset.empty()) { + return ReadFileResult::INVALID_PRESET; + } + return ReadFileResult::READ_OK; +} + +cmCMakePresetsGraph::ReadFileResult +cmCMakePresetsGraph::WorkflowPreset::VisitPresetInherit( + const cmCMakePresetsGraph::Preset& /*parentPreset*/) +{ + return ReadFileResult::READ_OK; +} + +cmCMakePresetsGraph::ReadFileResult +cmCMakePresetsGraph::WorkflowPreset::VisitPresetAfterInherit(int /* version */) +{ + return ReadFileResult::READ_OK; +} + std::string cmCMakePresetsGraph::GetFilename(const std::string& sourceDir) { return cmStrCat(sourceDir, "/CMakePresets.json"); @@ -901,8 +1025,9 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles) std::string filename = GetUserFilename(this->SourceDir); std::vector<File*> inProgressFiles; if (cmSystemTools::FileExists(filename)) { - auto result = this->ReadJSONFile(filename, RootType::User, - ReadReason::Root, inProgressFiles, file); + auto result = + this->ReadJSONFile(filename, RootType::User, ReadReason::Root, + inProgressFiles, file, this->errors); if (result != ReadFileResult::READ_OK) { return result; } @@ -910,8 +1035,9 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles) } else { filename = GetFilename(this->SourceDir); if (cmSystemTools::FileExists(filename)) { - auto result = this->ReadJSONFile( - filename, RootType::Project, ReadReason::Root, inProgressFiles, file); + auto result = + this->ReadJSONFile(filename, RootType::Project, ReadReason::Root, + inProgressFiles, file, this->errors); if (result != ReadFileResult::READ_OK) { return result; } @@ -928,6 +1054,8 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles) CHECK_OK(ComputePresetInheritance(this->ConfigurePresets, *this)); CHECK_OK(ComputePresetInheritance(this->BuildPresets, *this)); CHECK_OK(ComputePresetInheritance(this->TestPresets, *this)); + CHECK_OK(ComputePresetInheritance(this->PackagePresets, *this)); + CHECK_OK(ComputePresetInheritance(this->WorkflowPresets, *this)); for (auto& it : this->ConfigurePresets) { if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) { @@ -983,6 +1111,79 @@ cmCMakePresetsGraph::ReadProjectPresetsInternal(bool allowNoFiles) } } + for (auto& it : this->PackagePresets) { + if (!it.second.Unexpanded.Hidden) { + const auto configurePreset = + this->ConfigurePresets.find(it.second.Unexpanded.ConfigurePreset); + if (configurePreset == this->ConfigurePresets.end()) { + return ReadFileResult::INVALID_CONFIGURE_PRESET; + } + if (!it.second.Unexpanded.OriginFile->ReachableFiles.count( + configurePreset->second.Unexpanded.OriginFile)) { + return ReadFileResult::CONFIGURE_PRESET_UNREACHABLE_FROM_FILE; + } + + if (it.second.Unexpanded.InheritConfigureEnvironment.value_or(true)) { + it.second.Unexpanded.Environment.insert( + configurePreset->second.Unexpanded.Environment.begin(), + configurePreset->second.Unexpanded.Environment.end()); + } + } + + if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) { + return ReadFileResult::INVALID_MACRO_EXPANSION; + } + } + + for (auto& it : this->WorkflowPresets) { + using Type = WorkflowPreset::WorkflowStep::Type; + + const ConfigurePreset* configurePreset = nullptr; + for (auto const& step : it.second.Unexpanded.Steps) { + if (configurePreset == nullptr && step.PresetType != Type::Configure) { + return ReadFileResult::INVALID_WORKFLOW_STEPS; + } + if (configurePreset != nullptr && step.PresetType == Type::Configure) { + return ReadFileResult::INVALID_WORKFLOW_STEPS; + } + + ReadFileResult result; + switch (step.PresetType) { + case Type::Configure: + result = TryReachPresetFromWorkflow( + it.second.Unexpanded, this->ConfigurePresets, step.PresetName, + configurePreset); + break; + case Type::Build: + result = TryReachPresetFromWorkflow( + it.second.Unexpanded, this->BuildPresets, step.PresetName, + configurePreset); + break; + case Type::Test: + result = + TryReachPresetFromWorkflow(it.second.Unexpanded, this->TestPresets, + step.PresetName, configurePreset); + break; + case Type::Package: + result = TryReachPresetFromWorkflow( + it.second.Unexpanded, this->PackagePresets, step.PresetName, + configurePreset); + break; + } + if (result != ReadFileResult::READ_OK) { + return result; + } + } + + if (configurePreset == nullptr) { + return ReadFileResult::INVALID_WORKFLOW_STEPS; + } + + if (!ExpandMacros(*this, it.second.Unexpanded, it.second.Expanded)) { + return ReadFileResult::INVALID_MACRO_EXPANSION; + } + } + return ReadFileResult::READ_OK; } @@ -1026,6 +1227,10 @@ const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result) case ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED: return "File version must be 2 or higher for build and test preset " "support."; + case ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED: + return "File version must be 6 or higher for package preset support"; + case ReadFileResult::WORKFLOW_PRESETS_UNSUPPORTED: + return "File version must be 6 or higher for workflow preset support"; case ReadFileResult::INCLUDE_UNSUPPORTED: return "File version must be 4 or higher for include support"; case ReadFileResult::INVALID_INCLUDE: @@ -1047,6 +1252,12 @@ const char* cmCMakePresetsGraph::ResultToString(ReadFileResult result) case ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED: return "File version must be 5 or higher for testOutputTruncation " "preset support."; + case ReadFileResult::INVALID_WORKFLOW_STEPS: + return "Invalid workflow steps"; + case ReadFileResult::WORKFLOW_STEP_UNREACHABLE_FROM_FILE: + return "Workflow step is unreachable from preset's file"; + case ReadFileResult::CTEST_JUNIT_UNSUPPORTED: + return "File version must be 6 or higher for CTest JUnit output support"; } return "Unknown error"; @@ -1057,14 +1268,28 @@ void cmCMakePresetsGraph::ClearPresets() this->ConfigurePresets.clear(); this->BuildPresets.clear(); this->TestPresets.clear(); + this->PackagePresets.clear(); + this->WorkflowPresets.clear(); this->ConfigurePresetOrder.clear(); this->BuildPresetOrder.clear(); this->TestPresetOrder.clear(); + this->PackagePresetOrder.clear(); + this->WorkflowPresetOrder.clear(); this->Files.clear(); } +void cmCMakePresetsGraph::printPrecedingNewline(PrintPrecedingNewline* newline) +{ + if (newline) { + if (*newline == PrintPrecedingNewline::True) { + std::cout << std::endl; + } + *newline = PrintPrecedingNewline::True; + } +} + void cmCMakePresetsGraph::PrintPresets( const std::vector<const cmCMakePresetsGraph::Preset*>& presets) { @@ -1093,13 +1318,16 @@ void cmCMakePresetsGraph::PrintPresets( } } -void cmCMakePresetsGraph::PrintConfigurePresetList() const +void cmCMakePresetsGraph::PrintConfigurePresetList( + PrintPrecedingNewline* newline) const { - PrintConfigurePresetList([](const ConfigurePreset&) { return true; }); + PrintConfigurePresetList([](const ConfigurePreset&) { return true; }, + newline); } void cmCMakePresetsGraph::PrintConfigurePresetList( - const std::function<bool(const ConfigurePreset&)>& filter) const + const std::function<bool(const ConfigurePreset&)>& filter, + PrintPrecedingNewline* newline) const { std::vector<const cmCMakePresetsGraph::Preset*> presets; for (auto const& p : this->ConfigurePresetOrder) { @@ -1112,12 +1340,14 @@ void cmCMakePresetsGraph::PrintConfigurePresetList( } if (!presets.empty()) { + printPrecedingNewline(newline); std::cout << "Available configure presets:\n\n"; cmCMakePresetsGraph::PrintPresets(presets); } } -void cmCMakePresetsGraph::PrintBuildPresetList() const +void cmCMakePresetsGraph::PrintBuildPresetList( + PrintPrecedingNewline* newline) const { std::vector<const cmCMakePresetsGraph::Preset*> presets; for (auto const& p : this->BuildPresetOrder) { @@ -1130,12 +1360,14 @@ void cmCMakePresetsGraph::PrintBuildPresetList() const } if (!presets.empty()) { + printPrecedingNewline(newline); std::cout << "Available build presets:\n\n"; cmCMakePresetsGraph::PrintPresets(presets); } } -void cmCMakePresetsGraph::PrintTestPresetList() const +void cmCMakePresetsGraph::PrintTestPresetList( + PrintPrecedingNewline* newline) const { std::vector<const cmCMakePresetsGraph::Preset*> presets; for (auto const& p : this->TestPresetOrder) { @@ -1148,16 +1380,66 @@ void cmCMakePresetsGraph::PrintTestPresetList() const } if (!presets.empty()) { + printPrecedingNewline(newline); std::cout << "Available test presets:\n\n"; cmCMakePresetsGraph::PrintPresets(presets); } } +void cmCMakePresetsGraph::PrintPackagePresetList( + PrintPrecedingNewline* newline) const +{ + this->PrintPackagePresetList([](const PackagePreset&) { return true; }, + newline); +} + +void cmCMakePresetsGraph::PrintPackagePresetList( + const std::function<bool(const PackagePreset&)>& filter, + PrintPrecedingNewline* newline) const +{ + std::vector<const cmCMakePresetsGraph::Preset*> presets; + for (auto const& p : this->PackagePresetOrder) { + auto const& preset = this->PackagePresets.at(p); + if (!preset.Unexpanded.Hidden && preset.Expanded && + preset.Expanded->ConditionResult && filter(preset.Unexpanded)) { + presets.push_back( + static_cast<const cmCMakePresetsGraph::Preset*>(&preset.Unexpanded)); + } + } + + if (!presets.empty()) { + printPrecedingNewline(newline); + std::cout << "Available package presets:\n\n"; + cmCMakePresetsGraph::PrintPresets(presets); + } +} + +void cmCMakePresetsGraph::PrintWorkflowPresetList( + PrintPrecedingNewline* newline) const +{ + std::vector<const cmCMakePresetsGraph::Preset*> presets; + for (auto const& p : this->WorkflowPresetOrder) { + auto const& preset = this->WorkflowPresets.at(p); + if (!preset.Unexpanded.Hidden && preset.Expanded && + preset.Expanded->ConditionResult) { + presets.push_back( + static_cast<const cmCMakePresetsGraph::Preset*>(&preset.Unexpanded)); + } + } + + if (!presets.empty()) { + printPrecedingNewline(newline); + std::cout << "Available workflow presets:\n\n"; + cmCMakePresetsGraph::PrintPresets(presets); + } +} + void cmCMakePresetsGraph::PrintAllPresets() const { - this->PrintConfigurePresetList(); - std::cout << std::endl; - this->PrintBuildPresetList(); - std::cout << std::endl; - this->PrintTestPresetList(); + PrintPrecedingNewline newline = PrintPrecedingNewline::False; + this->PrintConfigurePresetList(&newline); + this->PrintBuildPresetList(&newline); + this->PrintTestPresetList(&newline); + this->PrintPackagePresetList(&newline); + this->PrintWorkflowPresetList(&newline); } diff --git a/Source/cmCMakePresetsGraph.h b/Source/cmCMakePresetsGraph.h index f1f8662..17c902b 100644 --- a/Source/cmCMakePresetsGraph.h +++ b/Source/cmCMakePresetsGraph.h @@ -41,6 +41,8 @@ public: CONFIGURE_PRESET_UNREACHABLE_FROM_FILE, INVALID_MACRO_EXPANSION, BUILD_TEST_PRESETS_UNSUPPORTED, + PACKAGE_PRESETS_UNSUPPORTED, + WORKFLOW_PRESETS_UNSUPPORTED, INCLUDE_UNSUPPORTED, INVALID_INCLUDE, INVALID_CONFIGURE_PRESET, @@ -50,8 +52,12 @@ public: TOOLCHAIN_FILE_UNSUPPORTED, CYCLIC_INCLUDE, TEST_OUTPUT_TRUNCATION_UNSUPPORTED, + INVALID_WORKFLOW_STEPS, + WORKFLOW_STEP_UNREACHABLE_FROM_FILE, + CTEST_JUNIT_UNSUPPORTED, }; + std::string errors; enum class ArchToolsetStrategy { Set, @@ -95,7 +101,7 @@ public: std::string Name; std::vector<std::string> Inherits; - bool Hidden; + bool Hidden = false; File* OriginFile; std::string DisplayName; std::string Description; @@ -225,6 +231,7 @@ public: cm::optional<bool> OutputOnFailure; cm::optional<bool> Quiet; std::string OutputLogFile; + std::string OutputJUnitFile; cm::optional<bool> LabelSummary; cm::optional<bool> SubprojectSummary; cm::optional<int> MaxPassedTestOutputSize; @@ -325,6 +332,79 @@ public: ReadFileResult VisitPresetAfterInherit(int /* version */) override; }; + class PackagePreset : public Preset + { + public: + PackagePreset() = default; + PackagePreset(PackagePreset&& /*other*/) = default; + PackagePreset(const PackagePreset& /*other*/) = default; + PackagePreset& operator=(const PackagePreset& /*other*/) = default; + ~PackagePreset() override = default; +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + PackagePreset& operator=(PackagePreset&& /*other*/) = default; +#else + // The move assignment operators for several STL classes did not become + // noexcept until C++17, which causes some tools to warn about this move + // assignment operator throwing an exception when it shouldn't. + PackagePreset& operator=(PackagePreset&& /*other*/) = delete; +#endif + + std::string ConfigurePreset; + cm::optional<bool> InheritConfigureEnvironment; + std::vector<std::string> Generators; + std::vector<std::string> Configurations; + std::map<std::string, std::string> Variables; + std::string ConfigFile; + + cm::optional<bool> DebugOutput; + cm::optional<bool> VerboseOutput; + + std::string PackageName; + std::string PackageVersion; + std::string PackageDirectory; + std::string VendorName; + + ReadFileResult VisitPresetInherit(const Preset& parent) override; + ReadFileResult VisitPresetAfterInherit(int /* version */) override; + }; + + class WorkflowPreset : public Preset + { + public: + WorkflowPreset() = default; + WorkflowPreset(WorkflowPreset&& /*other*/) = default; + WorkflowPreset(const WorkflowPreset& /*other*/) = default; + WorkflowPreset& operator=(const WorkflowPreset& /*other*/) = default; + ~WorkflowPreset() override = default; +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) + WorkflowPreset& operator=(WorkflowPreset&& /*other*/) = default; +#else + // The move assignment operators for several STL classes did not become + // noexcept until C++17, which causes some tools to warn about this move + // assignment operator throwing an exception when it shouldn't. + WorkflowPreset& operator=(WorkflowPreset&& /*other*/) = delete; +#endif + + class WorkflowStep + { + public: + enum class Type + { + Configure, + Build, + Test, + Package, + }; + Type PresetType; + std::string PresetName; + }; + + std::vector<WorkflowStep> Steps; + + ReadFileResult VisitPresetInherit(const Preset& parent) override; + ReadFileResult VisitPresetAfterInherit(int /* version */) override; + }; + template <class T> class PresetPair { @@ -336,10 +416,14 @@ public: std::map<std::string, PresetPair<ConfigurePreset>> ConfigurePresets; std::map<std::string, PresetPair<BuildPreset>> BuildPresets; std::map<std::string, PresetPair<TestPreset>> TestPresets; + std::map<std::string, PresetPair<PackagePreset>> PackagePresets; + std::map<std::string, PresetPair<WorkflowPreset>> WorkflowPresets; std::vector<std::string> ConfigurePresetOrder; std::vector<std::string> BuildPresetOrder; std::vector<std::string> TestPresetOrder; + std::vector<std::string> PackagePresetOrder; + std::vector<std::string> WorkflowPresetOrder; std::string SourceDir; std::vector<std::unique_ptr<File>> Files; @@ -382,13 +466,27 @@ public: return ""; } + enum class PrintPrecedingNewline + { + False, + True, + }; + static void printPrecedingNewline(PrintPrecedingNewline* p); + static void PrintPresets( const std::vector<const cmCMakePresetsGraph::Preset*>& presets); - void PrintConfigurePresetList() const; void PrintConfigurePresetList( - const std::function<bool(const ConfigurePreset&)>& filter) const; - void PrintBuildPresetList() const; - void PrintTestPresetList() const; + PrintPrecedingNewline* newline = nullptr) const; + void PrintConfigurePresetList( + const std::function<bool(const ConfigurePreset&)>& filter, + PrintPrecedingNewline* newline = nullptr) const; + void PrintBuildPresetList(PrintPrecedingNewline* newline = nullptr) const; + void PrintTestPresetList(PrintPrecedingNewline* newline = nullptr) const; + void PrintPackagePresetList(PrintPrecedingNewline* newline = nullptr) const; + void PrintPackagePresetList( + const std::function<bool(const PackagePreset&)>& filter, + PrintPrecedingNewline* newline = nullptr) const; + void PrintWorkflowPresetList(PrintPrecedingNewline* newline = nullptr) const; void PrintAllPresets() const; private: @@ -407,7 +505,7 @@ private: ReadFileResult ReadProjectPresetsInternal(bool allowNoFiles); ReadFileResult ReadJSONFile(const std::string& filename, RootType rootType, ReadReason readReason, - std::vector<File*>& inProgressFiles, - File*& file); + std::vector<File*>& inProgressFiles, File*& file, + std::string& errMsg); void ClearPresets(); }; diff --git a/Source/cmCMakePresetsGraphInternal.h b/Source/cmCMakePresetsGraphInternal.h index f7c7349..9e47a69 100644 --- a/Source/cmCMakePresetsGraphInternal.h +++ b/Source/cmCMakePresetsGraphInternal.h @@ -147,6 +147,14 @@ cmCMakePresetsGraph::ReadFileResult BuildPresetsHelper( cmCMakePresetsGraph::ReadFileResult TestPresetsHelper( std::vector<cmCMakePresetsGraph::TestPreset>& out, const Json::Value* value); +cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper( + std::vector<cmCMakePresetsGraph::PackagePreset>& out, + const Json::Value* value); + +cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper( + std::vector<cmCMakePresetsGraph::WorkflowPreset>& out, + const Json::Value* value); + cmJSONHelper<std::nullptr_t, cmCMakePresetsGraph::ReadFileResult> VendorHelper( cmCMakePresetsGraph::ReadFileResult error); diff --git a/Source/cmCMakePresetsGraphReadJSON.cxx b/Source/cmCMakePresetsGraphReadJSON.cxx index d11e839..eec53c1 100644 --- a/Source/cmCMakePresetsGraphReadJSON.cxx +++ b/Source/cmCMakePresetsGraphReadJSON.cxx @@ -30,11 +30,13 @@ using CacheVariable = cmCMakePresetsGraph::CacheVariable; using ConfigurePreset = cmCMakePresetsGraph::ConfigurePreset; using BuildPreset = cmCMakePresetsGraph::BuildPreset; using TestPreset = cmCMakePresetsGraph::TestPreset; +using PackagePreset = cmCMakePresetsGraph::PackagePreset; +using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset; using ArchToolsetStrategy = cmCMakePresetsGraph::ArchToolsetStrategy; using JSONHelperBuilder = cmJSONHelperBuilder<ReadFileResult>; constexpr int MIN_VERSION = 1; -constexpr int MAX_VERSION = 5; +constexpr int MAX_VERSION = 6; struct CMakeVersion { @@ -46,9 +48,11 @@ struct CMakeVersion struct RootPresets { CMakeVersion CMakeMinimumRequired; - std::vector<cmCMakePresetsGraph::ConfigurePreset> ConfigurePresets; - std::vector<cmCMakePresetsGraph::BuildPreset> BuildPresets; - std::vector<cmCMakePresetsGraph::TestPreset> TestPresets; + std::vector<ConfigurePreset> ConfigurePresets; + std::vector<BuildPreset> BuildPresets; + std::vector<TestPreset> TestPresets; + std::vector<PackagePreset> PackagePresets; + std::vector<WorkflowPreset> WorkflowPresets; std::vector<std::string> Include; }; @@ -281,6 +285,10 @@ auto const RootPresetsHelper = cmCMakePresetsGraphInternal::BuildPresetsHelper, false) .Bind("testPresets"_s, &RootPresets::TestPresets, cmCMakePresetsGraphInternal::TestPresetsHelper, false) + .Bind("packagePresets"_s, &RootPresets::PackagePresets, + cmCMakePresetsGraphInternal::PackagePresetsHelper, false) + .Bind("workflowPresets"_s, &RootPresets::WorkflowPresets, + cmCMakePresetsGraphInternal::WorkflowPresetsHelper, false) .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired, CMakeVersionHelper, false) .Bind("include"_s, &RootPresets::Include, IncludeVectorHelper, false) @@ -411,7 +419,7 @@ cmCMakePresetsGraph::ReadFileResult EnvironmentMapHelper( cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( const std::string& filename, RootType rootType, ReadReason readReason, - std::vector<File*>& inProgressFiles, File*& file) + std::vector<File*>& inProgressFiles, File*& file, std::string& errMsg) { ReadFileResult result; @@ -430,6 +438,7 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( cmsys::ifstream fin(filename.c_str()); if (!fin) { + errMsg = cmStrCat(filename, ": Failed to read file\n", errMsg); return ReadFileResult::FILE_NOT_FOUND; } // If there's a BOM, toss it. @@ -438,7 +447,8 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( Json::Value root; Json::CharReaderBuilder builder; Json::CharReaderBuilder::strictMode(&builder.settings_); - if (!Json::parseFromStream(builder, fin, &root, nullptr)) { + if (!Json::parseFromStream(builder, fin, &root, &errMsg)) { + errMsg = cmStrCat(filename, ":\n", errMsg); return ReadFileResult::JSON_PARSE_ERROR; } @@ -456,6 +466,16 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( return ReadFileResult::BUILD_TEST_PRESETS_UNSUPPORTED; } + // Support for package presets added in version 6. + if (v < 6 && root.isMember("packagePresets")) { + return ReadFileResult::PACKAGE_PRESETS_UNSUPPORTED; + } + + // Support for workflow presets added in version 6. + if (v < 6 && root.isMember("workflowPresets")) { + return ReadFileResult::WORKFLOW_PRESETS_UNSUPPORTED; + } + // Support for include added in version 4. if (v < 4 && root.isMember("include")) { return ReadFileResult::INCLUDE_UNSUPPORTED; @@ -490,6 +510,8 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( for (auto& preset : presets.ConfigurePresets) { preset.OriginFile = file; if (preset.Name.empty()) { + errMsg += R"(\n\t)"; + errMsg += filename; return ReadFileResult::INVALID_PRESET; } @@ -523,6 +545,8 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( for (auto& preset : presets.BuildPresets) { preset.OriginFile = file; if (preset.Name.empty()) { + errMsg += R"(\n\t)"; + errMsg += filename; return ReadFileResult::INVALID_PRESET; } @@ -564,17 +588,61 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( return ReadFileResult::TEST_OUTPUT_TRUNCATION_UNSUPPORTED; } + // Support for outputJUnitFile added in version 6. + if (v < 6 && preset.Output && !preset.Output->OutputJUnitFile.empty()) { + return ReadFileResult::CTEST_JUNIT_UNSUPPORTED; + } + this->TestPresetOrder.push_back(preset.Name); } + for (auto& preset : presets.PackagePresets) { + preset.OriginFile = file; + if (preset.Name.empty()) { + return ReadFileResult::INVALID_PRESET; + } + + PresetPair<PackagePreset> presetPair; + presetPair.Unexpanded = preset; + presetPair.Expanded = cm::nullopt; + if (!this->PackagePresets.emplace(preset.Name, presetPair).second) { + return ReadFileResult::DUPLICATE_PRESETS; + } + + // Support for conditions added in version 3, but this requires version 5 + // already, so no action needed. + + this->PackagePresetOrder.push_back(preset.Name); + } + + for (auto& preset : presets.WorkflowPresets) { + preset.OriginFile = file; + if (preset.Name.empty()) { + return ReadFileResult::INVALID_PRESET; + } + + PresetPair<WorkflowPreset> presetPair; + presetPair.Unexpanded = preset; + presetPair.Expanded = cm::nullopt; + if (!this->WorkflowPresets.emplace(preset.Name, presetPair).second) { + return ReadFileResult::DUPLICATE_PRESETS; + } + + // Support for conditions added in version 3, but this requires version 6 + // already, so no action needed. + + this->WorkflowPresetOrder.push_back(preset.Name); + } + auto const includeFile = [this, &inProgressFiles, file]( const std::string& include, RootType rootType2, - ReadReason readReason2) -> ReadFileResult { + ReadReason readReason2, + std::string& FailureMessage) -> ReadFileResult { ReadFileResult r; File* includedFile; if ((r = this->ReadJSONFile(include, rootType2, readReason2, - inProgressFiles, includedFile)) != - ReadFileResult::READ_OK) { + inProgressFiles, includedFile, + FailureMessage)) != ReadFileResult::READ_OK) { return r; } @@ -589,8 +657,8 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( include = cmStrCat(directory, '/', include); } - if ((result = includeFile(include, rootType, ReadReason::Included)) != - ReadFileResult::READ_OK) { + if ((result = includeFile(include, rootType, ReadReason::Included, + errMsg)) != ReadFileResult::READ_OK) { return result; } } @@ -599,7 +667,7 @@ cmCMakePresetsGraph::ReadFileResult cmCMakePresetsGraph::ReadJSONFile( auto cmakePresetsFilename = GetFilename(this->SourceDir); if (cmSystemTools::FileExists(cmakePresetsFilename)) { if ((result = includeFile(cmakePresetsFilename, RootType::Project, - ReadReason::Root)) != + ReadReason::Root, errMsg)) != ReadFileResult::READ_OK) { return result; } diff --git a/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx b/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx new file mode 100644 index 0000000..4ae51b1 --- /dev/null +++ b/Source/cmCMakePresetsGraphReadJSONPackagePresets.cxx @@ -0,0 +1,95 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include <cstddef> +#include <functional> +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include <cm/optional> +#include <cmext/string_view> + +#include <cm3p/json/value.h> + +#include "cmCMakePresetsGraph.h" +#include "cmCMakePresetsGraphInternal.h" +#include "cmJSONHelpers.h" + +namespace { +using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; +using PackagePreset = cmCMakePresetsGraph::PackagePreset; + +auto const OutputHelper = + cmJSONHelperBuilder<ReadFileResult>::Object<PackagePreset>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("debug"_s, &PackagePreset::DebugOutput, + cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) + .Bind("verbose"_s, &PackagePreset::VerboseOutput, + cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false); + +auto const VariableHelper = cmJSONHelperBuilder<ReadFileResult>::String( + ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE); + +auto const VariablesHelper = + cmJSONHelperBuilder<ReadFileResult>::Map<std::string>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper); + +auto const PackagePresetHelper = + cmJSONHelperBuilder<ReadFileResult>::Object<PackagePreset>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("name"_s, &PackagePreset::Name, + cmCMakePresetsGraphInternal::PresetStringHelper) + .Bind("inherits"_s, &PackagePreset::Inherits, + cmCMakePresetsGraphInternal::PresetVectorOneOrMoreStringHelper, + false) + .Bind("hidden"_s, &PackagePreset::Hidden, + cmCMakePresetsGraphInternal::PresetBoolHelper, false) + .Bind<std::nullptr_t>("vendor"_s, nullptr, + cmCMakePresetsGraphInternal::VendorHelper( + ReadFileResult::INVALID_PRESET), + false) + .Bind("displayName"_s, &PackagePreset::DisplayName, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("description"_s, &PackagePreset::Description, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("environment"_s, &PackagePreset::Environment, + cmCMakePresetsGraphInternal::EnvironmentMapHelper, false) + .Bind("configurePreset"_s, &PackagePreset::ConfigurePreset, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("inheritConfigureEnvironment"_s, + &PackagePreset::InheritConfigureEnvironment, + cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) + .Bind("generators"_s, &PackagePreset::Generators, + cmCMakePresetsGraphInternal::PresetVectorStringHelper, false) + .Bind("configurations"_s, &PackagePreset::Configurations, + cmCMakePresetsGraphInternal::PresetVectorStringHelper, false) + .Bind("variables"_s, &PackagePreset::Variables, VariablesHelper, false) + .Bind("configFile"_s, &PackagePreset::ConfigFile, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("output"_s, OutputHelper, false) + .Bind("packageName"_s, &PackagePreset::PackageName, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("packageVersion"_s, &PackagePreset::PackageVersion, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("packageDirectory"_s, &PackagePreset::PackageDirectory, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("vendorName"_s, &PackagePreset::VendorName, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("condition"_s, &PackagePreset::ConditionEvaluator, + cmCMakePresetsGraphInternal::PresetConditionHelper, false); +} + +namespace cmCMakePresetsGraphInternal { +cmCMakePresetsGraph::ReadFileResult PackagePresetsHelper( + std::vector<cmCMakePresetsGraph::PackagePreset>& out, + const Json::Value* value) +{ + static auto const helper = + cmJSONHelperBuilder<ReadFileResult>::Vector<PackagePreset>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, + PackagePresetHelper); + + return helper(out, value); +} +} diff --git a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx index c07d380..3856f63 100644 --- a/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx +++ b/Source/cmCMakePresetsGraphReadJSONTestPresets.cxx @@ -104,6 +104,8 @@ auto const TestPresetOptionalOutputHelper = cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) .Bind("outputLogFile"_s, &TestPreset::OutputOptions::OutputLogFile, cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("outputJUnitFile"_s, &TestPreset::OutputOptions::OutputJUnitFile, + cmCMakePresetsGraphInternal::PresetStringHelper, false) .Bind("labelSummary"_s, &TestPreset::OutputOptions::LabelSummary, cmCMakePresetsGraphInternal::PresetOptionalBoolHelper, false) .Bind("subprojectSummary"_s, diff --git a/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx b/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx new file mode 100644 index 0000000..33680a1 --- /dev/null +++ b/Source/cmCMakePresetsGraphReadJSONWorkflowPresets.cxx @@ -0,0 +1,95 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include <cstddef> +#include <functional> +#include <string> +#include <vector> + +#include <cmext/string_view> + +#include <cm3p/json/value.h> + +#include "cmCMakePresetsGraph.h" +#include "cmCMakePresetsGraphInternal.h" +#include "cmJSONHelpers.h" + +namespace { +using ReadFileResult = cmCMakePresetsGraph::ReadFileResult; +using WorkflowPreset = cmCMakePresetsGraph::WorkflowPreset; + +ReadFileResult WorkflowStepTypeHelper(WorkflowPreset::WorkflowStep::Type& out, + const Json::Value* value) +{ + if (!value) { + return ReadFileResult::INVALID_PRESET; + } + + if (!value->isString()) { + return ReadFileResult::INVALID_PRESET; + } + + if (value->asString() == "configure") { + out = WorkflowPreset::WorkflowStep::Type::Configure; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "build") { + out = WorkflowPreset::WorkflowStep::Type::Build; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "test") { + out = WorkflowPreset::WorkflowStep::Type::Test; + return ReadFileResult::READ_OK; + } + + if (value->asString() == "package") { + out = WorkflowPreset::WorkflowStep::Type::Package; + return ReadFileResult::READ_OK; + } + + return ReadFileResult::INVALID_PRESET; +} + +auto const WorkflowStepHelper = + cmJSONHelperBuilder<ReadFileResult>::Object<WorkflowPreset::WorkflowStep>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("type"_s, &WorkflowPreset::WorkflowStep::PresetType, + WorkflowStepTypeHelper) + .Bind("name"_s, &WorkflowPreset::WorkflowStep::PresetName, + cmCMakePresetsGraphInternal::PresetStringHelper); + +auto const WorkflowStepsHelper = + cmJSONHelperBuilder<ReadFileResult>::Vector<WorkflowPreset::WorkflowStep>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, + WorkflowStepHelper); + +auto const WorkflowPresetHelper = + cmJSONHelperBuilder<ReadFileResult>::Object<WorkflowPreset>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false) + .Bind("name"_s, &WorkflowPreset::Name, + cmCMakePresetsGraphInternal::PresetStringHelper) + .Bind<std::nullptr_t>("vendor"_s, nullptr, + cmCMakePresetsGraphInternal::VendorHelper( + ReadFileResult::INVALID_PRESET), + false) + .Bind("displayName"_s, &WorkflowPreset::DisplayName, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("description"_s, &WorkflowPreset::Description, + cmCMakePresetsGraphInternal::PresetStringHelper, false) + .Bind("steps"_s, &WorkflowPreset::Steps, WorkflowStepsHelper); +} + +namespace cmCMakePresetsGraphInternal { +cmCMakePresetsGraph::ReadFileResult WorkflowPresetsHelper( + std::vector<cmCMakePresetsGraph::WorkflowPreset>& out, + const Json::Value* value) +{ + static auto const helper = + cmJSONHelperBuilder<ReadFileResult>::Vector<WorkflowPreset>( + ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, + WorkflowPresetHelper); + + return helper(out, value); +} +} diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 66507a7..f60a1e9 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -2116,11 +2116,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, return false; } i++; - this->Impl->TestHandler.SetJUnitXMLFileName(std::string(args[i])); - // Turn test output compression off. - // This makes it easier to include test output in the resulting - // JUnit XML report. - this->Impl->CompressTestOutput = false; + this->SetOutputJUnitFileName(std::string(args[i])); } cm::string_view noTestsPrefix = "--no-tests="; @@ -2458,6 +2454,9 @@ bool cmCTest::SetArgsFromPreset(const std::string& presetName, if (!expandedPreset->Output->OutputLogFile.empty()) { this->SetOutputLogFileName(expandedPreset->Output->OutputLogFile); } + if (!expandedPreset->Output->OutputJUnitFile.empty()) { + this->SetOutputJUnitFileName(expandedPreset->Output->OutputJUnitFile); + } this->Impl->LabelSummary = expandedPreset->Output->LabelSummary.value_or(true); @@ -3541,6 +3540,15 @@ void cmCTest::SetOutputLogFileName(const std::string& name) } } +void cmCTest::SetOutputJUnitFileName(const std::string& name) +{ + this->Impl->TestHandler.SetJUnitXMLFileName(name); + // Turn test output compression off. + // This makes it easier to include test output in the resulting + // JUnit XML report. + this->Impl->CompressTestOutput = false; +} + static const char* cmCTestStringLogType[] = { "DEBUG", "OUTPUT", "HANDLER_OUTPUT", diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 551c116..0017b3e 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -359,6 +359,9 @@ public: /** Set the output log file name */ void SetOutputLogFileName(const std::string& name); + /** Set the output JUnit file name */ + void SetOutputJUnitFileName(const std::string& name); + /** Set the visual studio or Xcode config type */ void SetConfigType(const std::string& ct); diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index c6296f9..27f2156 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -14,13 +14,13 @@ #include "cmAddLibraryCommand.h" #include "cmAddSubDirectoryCommand.h" #include "cmAddTestCommand.h" +#include "cmBlockCommand.h" #include "cmBreakCommand.h" #include "cmBuildCommand.h" #include "cmCMakeLanguageCommand.h" #include "cmCMakeMinimumRequired.h" #include "cmCMakePathCommand.h" #include "cmCMakePolicyCommand.h" -#include "cmCommand.h" #include "cmConfigureFileCommand.h" #include "cmContinueCommand.h" #include "cmCreateTestSourceList.h" @@ -127,6 +127,7 @@ void GetScriptingCommands(cmState* state) state->AddFlowControlCommand("macro", cmMacroCommand); state->AddFlowControlCommand("return", cmReturnCommand); state->AddFlowControlCommand("while", cmWhileCommand); + state->AddFlowControlCommand("block", cmBlockCommand); state->AddBuiltinCommand("cmake_language", cmCMakeLanguageCommand); state->AddBuiltinCommand("cmake_minimum_required", cmCMakeMinimumRequired); @@ -199,6 +200,10 @@ void GetScriptingCommands(cmState* state) "An ENDWHILE command was found outside of a proper " "WHILE ENDWHILE structure. Or its arguments did not " "match the opening WHILE command."); + state->AddUnexpectedFlowControlCommand( + "endblock", + "An ENDBLOCK command was found outside of a proper " + "BLOCK ENDBLOCK structure."); #if !defined(CMAKE_BOOTSTRAP) state->AddBuiltinCommand("cmake_host_system_information", @@ -220,6 +225,8 @@ void GetScriptingCommands(cmState* state) void GetProjectCommands(cmState* state) { + state->AddBuiltinCommand("add_compile_definitions", + cmAddCompileDefinitionsCommand); state->AddBuiltinCommand("add_custom_command", cmAddCustomCommandCommand); state->AddBuiltinCommand("add_custom_target", cmAddCustomTargetCommand); state->AddBuiltinCommand("add_definitions", cmAddDefinitionsCommand); @@ -264,15 +271,12 @@ void GetProjectCommands(cmState* state) cmTargetLinkLibrariesCommand); state->AddBuiltinCommand("target_link_options", cmTargetLinkOptionsCommand); state->AddBuiltinCommand("target_sources", cmTargetSourcesCommand); - state->AddBuiltinCommand("try_compile", - cm::make_unique<cmTryCompileCommand>()); - state->AddBuiltinCommand("try_run", cm::make_unique<cmTryRunCommand>()); + state->AddBuiltinCommand("try_compile", cmTryCompileCommand); + state->AddBuiltinCommand("try_run", cmTryRunCommand); state->AddBuiltinCommand("target_precompile_headers", cmTargetPrecompileHeadersCommand); #if !defined(CMAKE_BOOTSTRAP) - state->AddBuiltinCommand("add_compile_definitions", - cmAddCompileDefinitionsCommand); state->AddBuiltinCommand("add_compile_options", cmAddCompileOptionsCommand); state->AddBuiltinCommand("aux_source_directory", cmAuxSourceDirectoryCommand); diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index ba95168..5fe6756 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -9,6 +9,7 @@ #include "cmComputeLinkInformation.h" #include "cmGeneratorTarget.h" #include "cmGlobalCommonGenerator.h" +#include "cmGlobalGenerator.h" #include "cmLocalCommonGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -175,6 +176,9 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories( cmLocalGenerator* lg = linkee->GetLocalGenerator(); std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', lg->GetTargetDirectory(linkee)); + if (lg->GetGlobalGenerator()->IsMultiConfig()) { + di = cmStrCat(di, '/', config); + } dirs.push_back(std::move(di)); } } diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index cda70fc..044f69f 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1566,8 +1566,9 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry) if (target->IsFrameworkOnApple() && !this->GlobalGenerator->IsXcode()) { // Add the framework directory and the framework item itself - auto fwItems = this->GlobalGenerator->SplitFrameworkPath(item.Value, true); - if (!fwItems) { + auto fwDescriptor = this->GlobalGenerator->SplitFrameworkPath( + item.Value, cmGlobalGenerator::FrameworkFormat::Extended); + if (!fwDescriptor) { this->CMakeInstance->IssueMessage( MessageType::FATAL_ERROR, cmStrCat("Could not parse framework path \"", item.Value, @@ -1575,12 +1576,13 @@ void cmComputeLinkInformation::AddTargetItem(LinkEntry const& entry) item.Backtrace); return; } - if (!fwItems->first.empty()) { + if (!fwDescriptor->Directory.empty()) { // Add the directory portion to the framework search path. - this->AddFrameworkPath(fwItems->first); + this->AddFrameworkPath(fwDescriptor->Directory); } if (cmHasSuffix(entry.Feature, "FRAMEWORK"_s)) { - this->Items.emplace_back(fwItems->second, ItemIsPath::Yes, target, + this->Items.emplace_back(fwDescriptor->GetLinkName(), ItemIsPath::Yes, + target, this->FindLibraryFeature(entry.Feature)); } else { this->Items.emplace_back( @@ -1851,9 +1853,11 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry) std::string const& item = entry.Item.Value; // Try to separate the framework name and path. - auto fwItems = - this->GlobalGenerator->SplitFrameworkPath(item, entry.Feature != DEFAULT); - if (!fwItems) { + auto fwDescriptor = this->GlobalGenerator->SplitFrameworkPath( + item, + entry.Feature == DEFAULT ? cmGlobalGenerator::FrameworkFormat::Relaxed + : cmGlobalGenerator::FrameworkFormat::Extended); + if (!fwDescriptor) { std::ostringstream e; e << "Could not parse framework path \"" << item << "\" " << "linked by target " << this->Target->GetName() << "."; @@ -1861,18 +1865,14 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry) return; } - std::string fw_path = std::move(fwItems->first); - std::string fw = std::move(fwItems->second); - std::string full_fw = cmStrCat(fw, ".framework/", fw); - + const std::string& fw_path = fwDescriptor->Directory; if (!fw_path.empty()) { - full_fw = cmStrCat(fw_path, '/', full_fw); // Add the directory portion to the framework search path. this->AddFrameworkPath(fw_path); } // add runtime information - this->AddLibraryRuntimeInfo(full_fw); + this->AddLibraryRuntimeInfo(fwDescriptor->GetFullPath()); if (entry.Feature == DEFAULT) { // ensure FRAMEWORK feature is loaded @@ -1887,9 +1887,9 @@ void cmComputeLinkInformation::AddFrameworkItem(LinkEntry const& entry) ? "FRAMEWORK" : entry.Feature)); } else { - this->Items.emplace_back(fw, ItemIsPath::Yes, nullptr, - this->FindLibraryFeature(entry.Feature == DEFAULT - ? "FRAMEWORK" + this->Items.emplace_back( + fwDescriptor->GetLinkName(), ItemIsPath::Yes, nullptr, + this->FindLibraryFeature(entry.Feature == DEFAULT ? "FRAMEWORK" : entry.Feature)); } } @@ -2252,15 +2252,11 @@ void cmComputeLinkInformation::AddLibraryRuntimeInfo( // It could be an Apple framework if (!is_shared_library) { - if (fullPath.find(".framework") != std::string::npos) { - static cmsys::RegularExpression splitFramework( - "^(.*)/(.*).framework/(.*)$"); - if (splitFramework.find(fullPath) && - (std::string::npos != - splitFramework.match(3).find(splitFramework.match(2)))) { - is_shared_library = true; - } - } + is_shared_library = + this->GlobalGenerator + ->SplitFrameworkPath(fullPath, + cmGlobalGenerator::FrameworkFormat::Strict) + .has_value(); } if (!is_shared_library) { diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index 6a419f6..90f3de0 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -14,10 +14,15 @@ #pragma warning(disable : 1572) /* floating-point equality test */ #endif +#if defined(__LCC__) && defined(__EDG__) && (__LCC__ == 123) +#pragma diag_suppress 2910 /* excess -Wunused-function in 1.23.x */ +#endif + #cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE #cmakedefine HAVE_UNSETENV #cmakedefine CMake_USE_MACH_PARSER #cmakedefine CMake_USE_XCOFF_PARSER +#cmakedefine CMAKE_USE_WMAKE #define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@ #define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@" #define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@" @@ -28,3 +33,11 @@ #if defined(_WIN32) && !defined(NOMINMAX) # define NOMINMAX #endif + +#cmakedefine CURL_CA_BUNDLE "@CURL_CA_BUNDLE@" +#cmakedefine CURL_CA_PATH "@CURL_CA_PATH@" + +#cmakedefine01 CMake_STAT_HAS_ST_MTIM +#cmakedefine01 CMake_STAT_HAS_ST_MTIMESPEC + +#cmakedefine KWSYS_ENCODING_DEFAULT_CODEPAGE @KWSYS_ENCODING_DEFAULT_CODEPAGE@ diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index b1d37a6..867f984 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCoreTryCompile.h" +#include <array> #include <cstdio> #include <cstring> #include <set> @@ -12,13 +13,16 @@ #include <cmext/string_view> #include "cmsys/Directory.hxx" +#include "cmsys/FStream.hxx" +#include "cmArgumentParser.h" #include "cmExportTryCompileFileGenerator.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" +#include "cmRange.h" #include "cmState.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" @@ -28,142 +32,7 @@ #include "cmake.h" namespace { -class LanguageStandardState -{ -public: - LanguageStandardState(std::string&& lang) - : StandardFlag(lang + "_STANDARD") - , RequiredFlag(lang + "_STANDARD_REQUIRED") - , ExtensionFlag(lang + "_EXTENSIONS") - { - } - - void Enabled(bool isEnabled) { this->IsEnabled = isEnabled; } - - bool UpdateIfMatches(std::vector<std::string> const& argv, size_t& index) - { - bool updated = false; - if (argv[index] == this->StandardFlag) { - this->DidStandard = true; - this->StandardValue = argv[++index]; - updated = true; - } else if (argv[index] == this->RequiredFlag) { - this->DidStandardRequired = true; - this->RequiredValue = argv[++index]; - updated = true; - } else if (argv[index] == this->ExtensionFlag) { - this->DidExtensions = true; - this->ExtensionValue = argv[++index]; - updated = true; - } - return updated; - } - - bool Validate(cmMakefile* const makefile) const - { - if (this->DidStandard) { - makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat(this->StandardFlag, - " allowed only in source file signature.")); - return false; - } - if (this->DidStandardRequired) { - makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat(this->RequiredFlag, - " allowed only in source file signature.")); - return false; - } - if (this->DidExtensions) { - makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat(this->ExtensionFlag, - " allowed only in source file signature.")); - return false; - } - - return true; - } - - bool DidNone() const - { - return !this->DidStandard && !this->DidStandardRequired && - !this->DidExtensions; - } - - void LoadUnsetPropertyValues(cmMakefile* const makefile, bool honorStandard, - bool warnCMP0067, - std::vector<std::string>& warnCMP0067Variables) - { - if (!this->IsEnabled) { - return; - } - - auto lookupStdVar = [&](std::string const& var) -> std::string { - std::string value = makefile->GetSafeDefinition(var); - if (warnCMP0067 && !value.empty()) { - value.clear(); - warnCMP0067Variables.emplace_back(var); - } - return value; - }; - - if (honorStandard || warnCMP0067) { - if (!this->DidStandard) { - this->StandardValue = - lookupStdVar(cmStrCat("CMAKE_", this->StandardFlag)); - } - if (!this->DidStandardRequired) { - this->RequiredValue = - lookupStdVar(cmStrCat("CMAKE_", this->RequiredFlag)); - } - if (!this->DidExtensions) { - this->ExtensionValue = - lookupStdVar(cmStrCat("CMAKE_", this->ExtensionFlag)); - } - } - } - - void WriteProperties(FILE* fout, std::string const& targetName) const - { - if (!this->IsEnabled) { - return; - } - - auto writeProp = [&](std::string const& prop, std::string const& value) { - fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n", - targetName.c_str(), - cmOutputConverter::EscapeForCMake(prop).c_str(), - cmOutputConverter::EscapeForCMake(value).c_str()); - }; - - if (!this->StandardValue.empty()) { - writeProp(this->StandardFlag, this->StandardValue); - } - if (!this->RequiredValue.empty()) { - writeProp(this->RequiredFlag, this->RequiredValue); - } - if (!this->ExtensionValue.empty()) { - writeProp(this->ExtensionFlag, this->ExtensionValue); - } - } - -private: - bool IsEnabled = false; - bool DidStandard = false; - bool DidStandardRequired = false; - bool DidExtensions = false; - - std::string StandardFlag; - std::string RequiredFlag; - std::string ExtensionFlag; - - std::string StandardValue; - std::string RequiredValue; - std::string ExtensionValue; -}; - +constexpr const char* unique_binary_directory = "CMAKE_BINARY_DIR_USE_MKDTEMP"; constexpr size_t lang_property_start = 0; constexpr size_t lang_property_size = 4; constexpr size_t pie_property_start = 4; @@ -226,6 +95,8 @@ std::string const kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES = std::string const kCMAKE_WARN_DEPRECATED = "CMAKE_WARN_DEPRECATED"; std::string const kCMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT = "CMAKE_WATCOM_RUNTIME_LIBRARY_DEFAULT"; +std::string const kCMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT = + "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT"; /* GHS Multi platform variables */ std::set<std::string> const ghs_platform_vars{ @@ -233,114 +104,249 @@ std::set<std::string> const ghs_platform_vars{ "GHS_OS_ROOT", "GHS_OS_DIR", "GHS_BSP_NAME", "GHS_OS_DIR_OPTION" }; +using Arguments = cmCoreTryCompile::Arguments; + +ArgumentParser::Continue TryCompileLangProp(Arguments& args, + cm::string_view key, + cm::string_view val) +{ + args.LangProps[std::string(key)] = std::string(val); + return ArgumentParser::Continue::No; +} + +ArgumentParser::Continue TryCompileCompileDefs(Arguments& args, + cm::string_view val) +{ + cmExpandList(val, args.CompileDefs); + return ArgumentParser::Continue::Yes; } -int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, - bool isTryRun) +cmArgumentParser<Arguments> makeTryCompileParser( + const cmArgumentParser<Arguments>& base) +{ + return cmArgumentParser<Arguments>{ base }.Bind("OUTPUT_VARIABLE"_s, + &Arguments::OutputVariable); +} + +cmArgumentParser<Arguments> makeTryRunParser( + const cmArgumentParser<Arguments>& base) +{ + return cmArgumentParser<Arguments>{ base } + .Bind("COMPILE_OUTPUT_VARIABLE"_s, &Arguments::CompileOutputVariable) + .Bind("RUN_OUTPUT_VARIABLE"_s, &Arguments::RunOutputVariable) + .Bind("RUN_OUTPUT_STDOUT_VARIABLE"_s, &Arguments::RunOutputStdOutVariable) + .Bind("RUN_OUTPUT_STDERR_VARIABLE"_s, &Arguments::RunOutputStdErrVariable) + .Bind("WORKING_DIRECTORY"_s, &Arguments::RunWorkingDirectory) + .Bind("ARGS"_s, &Arguments::RunArgs) + /* keep semicolon on own line */; +} + +#define BIND_LANG_PROPS(lang) \ + Bind(#lang "_STANDARD"_s, TryCompileLangProp) \ + .Bind(#lang "_STANDARD_REQUIRED"_s, TryCompileLangProp) \ + .Bind(#lang "_EXTENSIONS"_s, TryCompileLangProp) + +auto const TryCompileBaseArgParser = + cmArgumentParser<Arguments>{} + .Bind(0, &Arguments::CompileResultVariable) + .Bind("NO_CACHE"_s, &Arguments::NoCache) + .Bind("CMAKE_FLAGS"_s, &Arguments::CMakeFlags) + .Bind("__CMAKE_INTERNAL"_s, &Arguments::CMakeInternal) + /* keep semicolon on own line */; + +auto const TryCompileBaseSourcesArgParser = + cmArgumentParser<Arguments>{ TryCompileBaseArgParser } + .Bind("SOURCES"_s, &Arguments::Sources) + .Bind("COMPILE_DEFINITIONS"_s, TryCompileCompileDefs, + ArgumentParser::ExpectAtLeast{ 0 }) + .Bind("LINK_LIBRARIES"_s, &Arguments::LinkLibraries) + .Bind("LINK_OPTIONS"_s, &Arguments::LinkOptions) + .Bind("COPY_FILE"_s, &Arguments::CopyFileTo) + .Bind("COPY_FILE_ERROR"_s, &Arguments::CopyFileError) + .BIND_LANG_PROPS(C) + .BIND_LANG_PROPS(CUDA) + .BIND_LANG_PROPS(CXX) + .BIND_LANG_PROPS(HIP) + .BIND_LANG_PROPS(OBJC) + .BIND_LANG_PROPS(OBJCXX) + /* keep semicolon on own line */; + +auto const TryCompileBaseNewSourcesArgParser = + cmArgumentParser<Arguments>{ TryCompileBaseSourcesArgParser } + .Bind("SOURCE_FROM_CONTENT"_s, &Arguments::SourceFromContent) + .Bind("SOURCE_FROM_VAR"_s, &Arguments::SourceFromVar) + .Bind("SOURCE_FROM_FILE"_s, &Arguments::SourceFromFile) + /* keep semicolon on own line */; + +auto const TryCompileBaseProjectArgParser = + cmArgumentParser<Arguments>{ TryCompileBaseArgParser } + .Bind("PROJECT"_s, &Arguments::ProjectName) + .Bind("SOURCE_DIR"_s, &Arguments::SourceDirectoryOrFile) + .Bind("BINARY_DIR"_s, &Arguments::BinaryDirectory) + .Bind("TARGET"_s, &Arguments::TargetName) + /* keep semicolon on own line */; + +auto const TryCompileProjectArgParser = + makeTryCompileParser(TryCompileBaseProjectArgParser); + +auto const TryCompileSourcesArgParser = + makeTryCompileParser(TryCompileBaseNewSourcesArgParser); + +auto const TryCompileOldArgParser = + makeTryCompileParser(TryCompileBaseSourcesArgParser) + .Bind(1, &Arguments::BinaryDirectory) + .Bind(2, &Arguments::SourceDirectoryOrFile) + .Bind(3, &Arguments::ProjectName) + .Bind(4, &Arguments::TargetName) + /* keep semicolon on own line */; + +auto const TryRunSourcesArgParser = + makeTryRunParser(TryCompileBaseNewSourcesArgParser); + +auto const TryRunOldArgParser = makeTryRunParser(TryCompileOldArgParser); + +#undef BIND_LANG_PROPS +} + +Arguments cmCoreTryCompile::ParseArgs( + const cmRange<std::vector<std::string>::const_iterator>& args, + const cmArgumentParser<Arguments>& parser, + std::vector<std::string>& unparsedArguments) +{ + auto arguments = parser.Parse(args, &unparsedArguments, 0); + if (!arguments.MaybeReportError(*(this->Makefile)) && + !unparsedArguments.empty()) { + std::string m = "Unknown arguments:"; + for (const auto& i : unparsedArguments) { + m = cmStrCat(m, "\n \"", i, "\""); + } + this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m); + } + return arguments; +} + +Arguments cmCoreTryCompile::ParseArgs( + cmRange<std::vector<std::string>::const_iterator> args, bool isTryRun) +{ + std::vector<std::string> unparsedArguments; + const auto& second = *(++args.begin()); + + if (!isTryRun && second == "PROJECT") { + // New PROJECT signature (try_compile only). + auto arguments = + this->ParseArgs(args, TryCompileProjectArgParser, unparsedArguments); + if (!arguments.BinaryDirectory) { + arguments.BinaryDirectory = unique_binary_directory; + } + return arguments; + } + + if (cmHasLiteralPrefix(second, "SOURCE")) { + // New SOURCES signature. + auto arguments = this->ParseArgs( + args, isTryRun ? TryRunSourcesArgParser : TryCompileSourcesArgParser, + unparsedArguments); + arguments.BinaryDirectory = unique_binary_directory; + return arguments; + } + + // Old signature. + auto arguments = this->ParseArgs( + args, isTryRun ? TryRunOldArgParser : TryCompileOldArgParser, + unparsedArguments); + // For historical reasons, treat some empty-valued keyword + // arguments as if they were not specified at all. + if (arguments.OutputVariable && arguments.OutputVariable->empty()) { + arguments.OutputVariable = cm::nullopt; + } + if (isTryRun) { + if (arguments.CompileOutputVariable && + arguments.CompileOutputVariable->empty()) { + arguments.CompileOutputVariable = cm::nullopt; + } + if (arguments.RunOutputVariable && arguments.RunOutputVariable->empty()) { + arguments.RunOutputVariable = cm::nullopt; + } + if (arguments.RunOutputStdOutVariable && + arguments.RunOutputStdOutVariable->empty()) { + arguments.RunOutputStdOutVariable = cm::nullopt; + } + if (arguments.RunOutputStdErrVariable && + arguments.RunOutputStdErrVariable->empty()) { + arguments.RunOutputStdErrVariable = cm::nullopt; + } + if (arguments.RunWorkingDirectory && + arguments.RunWorkingDirectory->empty()) { + arguments.RunWorkingDirectory = cm::nullopt; + } + } + return arguments; +} + +bool cmCoreTryCompile::TryCompileCode(Arguments& arguments, + cmStateEnums::TargetType targetType) { - this->BinaryDirectory = argv[1]; this->OutputFile.clear(); // which signature were we called with ? this->SrcFileSignature = true; - cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE; - cmValue tt = this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE"); - if (!isTryRun && cmNonempty(tt)) { - if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) { - targetType = cmStateEnums::EXECUTABLE; - } else if (*tt == - cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY)) { - targetType = cmStateEnums::STATIC_LIBRARY; - } else { + bool useUniqueBinaryDirectory = false; + std::string sourceDirectory; + std::string projectName; + std::string targetName; + if (arguments.ProjectName) { + this->SrcFileSignature = false; + if (!arguments.SourceDirectoryOrFile || + arguments.SourceDirectoryOrFile->empty()) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "No <srcdir> specified."); + return false; + } + sourceDirectory = *arguments.SourceDirectoryOrFile; + projectName = *arguments.ProjectName; + if (arguments.TargetName) { + targetName = *arguments.TargetName; + } + } else { + projectName = "CMAKE_TRY_COMPILE"; + /* Use a random file name to avoid rapid creation and deletion + of the same executable name (some filesystems fail on that). */ + char targetNameBuf[64]; + snprintf(targetNameBuf, sizeof(targetNameBuf), "cmTC_%05x", + cmSystemTools::RandomSeed() & 0xFFFFF); + targetName = targetNameBuf; + } + + if (!arguments.BinaryDirectory || arguments.BinaryDirectory->empty()) { + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, + "No <bindir> specified."); + return false; + } + if (*arguments.BinaryDirectory == unique_binary_directory) { + // leave empty until we're ready to create it, so we don't try to remove + // a non-existing directory if we abort due to e.g. bad arguments + this->BinaryDirectory.clear(); + useUniqueBinaryDirectory = true; + } else { + if (!cmSystemTools::FileIsFullPath(*arguments.BinaryDirectory)) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - cmStrCat("Invalid value '", *tt, - "' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only '", - cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE), - "' and '", - cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY), - "' are allowed.")); - return -1; + cmStrCat("<bindir> is not an absolute path:\n '", + *arguments.BinaryDirectory, "'")); + return false; + } + this->BinaryDirectory = *arguments.BinaryDirectory; + // compute the binary dir when TRY_COMPILE is called with a src file + // signature + if (this->SrcFileSignature) { + this->BinaryDirectory += "/CMakeFiles/CMakeTmp"; } } - std::string sourceDirectory = argv[2]; - std::string projectName; - std::string targetName; - std::vector<std::string> cmakeFlags(1, "CMAKE_FLAGS"); // fake argv[0] - std::vector<std::string> compileDefs; - std::string cmakeInternal; - std::string outputVariable; - std::string copyFile; - std::string copyFileError; - LanguageStandardState cState("C"); - LanguageStandardState cudaState("CUDA"); - LanguageStandardState cxxState("CXX"); - LanguageStandardState hipState("HIP"); - LanguageStandardState objcState("OBJC"); - LanguageStandardState objcxxState("OBJCXX"); std::vector<std::string> targets; - std::vector<std::string> linkOptions; - std::string libsToLink = " "; - bool useOldLinkLibs = true; - char targetNameBuf[64]; - bool didOutputVariable = false; - bool didCopyFile = false; - bool didCopyFileError = false; - bool useSources = argv[2] == "SOURCES"; - std::vector<std::string> sources; - - enum Doing - { - DoingNone, - DoingCMakeFlags, - DoingCompileDefinitions, - DoingLinkOptions, - DoingLinkLibraries, - DoingOutputVariable, - DoingCopyFile, - DoingCopyFileError, - DoingSources, - DoingCMakeInternal - }; - Doing doing = useSources ? DoingSources : DoingNone; - for (size_t i = 3; i < argv.size(); ++i) { - if (argv[i] == "CMAKE_FLAGS") { - doing = DoingCMakeFlags; - } else if (argv[i] == "COMPILE_DEFINITIONS") { - doing = DoingCompileDefinitions; - } else if (argv[i] == "LINK_OPTIONS") { - doing = DoingLinkOptions; - } else if (argv[i] == "LINK_LIBRARIES") { - doing = DoingLinkLibraries; - useOldLinkLibs = false; - } else if (argv[i] == "OUTPUT_VARIABLE") { - doing = DoingOutputVariable; - didOutputVariable = true; - } else if (argv[i] == "COPY_FILE") { - doing = DoingCopyFile; - didCopyFile = true; - } else if (argv[i] == "COPY_FILE_ERROR") { - doing = DoingCopyFileError; - didCopyFileError = true; - } else if (cState.UpdateIfMatches(argv, i) || - cxxState.UpdateIfMatches(argv, i) || - cudaState.UpdateIfMatches(argv, i) || - hipState.UpdateIfMatches(argv, i) || - objcState.UpdateIfMatches(argv, i) || - objcxxState.UpdateIfMatches(argv, i)) { - continue; - } else if (argv[i] == "__CMAKE_INTERNAL") { - doing = DoingCMakeInternal; - } else if (doing == DoingCMakeFlags) { - cmakeFlags.emplace_back(argv[i]); - } else if (doing == DoingCompileDefinitions) { - cmExpandList(argv[i], compileDefs); - } else if (doing == DoingLinkOptions) { - linkOptions.emplace_back(argv[i]); - } else if (doing == DoingLinkLibraries) { - libsToLink += "\"" + cmTrimWhitespace(argv[i]) + "\" "; - if (cmTarget* tgt = this->Makefile->FindTargetToUse(argv[i])) { + if (arguments.LinkLibraries) { + for (std::string const& i : *arguments.LinkLibraries) { + if (cmTarget* tgt = this->Makefile->FindTargetToUse(i)) { switch (tgt->GetType()) { case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::STATIC_LIBRARY: @@ -359,114 +365,94 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, "IMPORTED LINK_LIBRARIES. Got ", tgt->GetName(), " of type ", cmState::GetTargetTypeName(tgt->GetType()), ".")); - return -1; + return false; } if (tgt->IsImported()) { - targets.emplace_back(argv[i]); + targets.emplace_back(i); } } - } else if (doing == DoingOutputVariable) { - outputVariable = argv[i]; - doing = DoingNone; - } else if (doing == DoingCopyFile) { - copyFile = argv[i]; - doing = DoingNone; - } else if (doing == DoingCopyFileError) { - copyFileError = argv[i]; - doing = DoingNone; - } else if (doing == DoingSources) { - sources.emplace_back(argv[i]); - } else if (doing == DoingCMakeInternal) { - cmakeInternal = argv[i]; - doing = DoingNone; - } else if (i == 3) { - this->SrcFileSignature = false; - projectName = argv[i]; - } else if (i == 4 && !this->SrcFileSignature) { - targetName = argv[i]; - } else { - std::ostringstream m; - m << "try_compile given unknown argument \"" << argv[i] << "\"."; - this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, m.str()); } } - if (didCopyFile && copyFile.empty()) { + if (arguments.CopyFileTo && arguments.CopyFileTo->empty()) { this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "COPY_FILE must be followed by a file path"); - return -1; + return false; } - if (didCopyFileError && copyFileError.empty()) { + if (arguments.CopyFileError && arguments.CopyFileError->empty()) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, "COPY_FILE_ERROR must be followed by a variable name"); - return -1; + return false; } - if (didCopyFileError && !didCopyFile) { + if (arguments.CopyFileError && !arguments.CopyFileTo) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, "COPY_FILE_ERROR may be used only with COPY_FILE"); - return -1; - } - - if (didOutputVariable && outputVariable.empty()) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "OUTPUT_VARIABLE must be followed by a variable name"); - return -1; + return false; } - if (useSources && sources.empty()) { + if (arguments.Sources && arguments.Sources->empty()) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, "SOURCES must be followed by at least one source file"); - return -1; + return false; } - if (!this->SrcFileSignature) { - if (!cState.Validate(this->Makefile)) { - return -1; - } - if (!cudaState.Validate(this->Makefile)) { - return -1; - } - if (!hipState.Validate(this->Makefile)) { - return -1; - } - if (!cxxState.Validate(this->Makefile)) { - return -1; + if (this->SrcFileSignature) { + if (arguments.SourceFromContent && + arguments.SourceFromContent->size() % 2) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "SOURCE_FROM_CONTENT requires exactly two arguments"); + return false; } - if (!objcState.Validate(this->Makefile)) { - return -1; + if (arguments.SourceFromVar && arguments.SourceFromVar->size() % 2) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "SOURCE_FROM_VAR requires exactly two arguments"); + return false; } - if (!objcxxState.Validate(this->Makefile)) { - return -1; + if (arguments.SourceFromFile && arguments.SourceFromFile->size() % 2) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + "SOURCE_FROM_FILE requires exactly two arguments"); + return false; } - } - - // compute the binary dir when TRY_COMPILE is called with a src file - // signature - if (this->SrcFileSignature) { - this->BinaryDirectory += "/CMakeFiles/CMakeTmp"; } else { // only valid for srcfile signatures - if (!compileDefs.empty()) { + if (!arguments.LangProps.empty()) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat(arguments.LangProps.begin()->first, + " allowed only in source file signature")); + return false; + } + if (!arguments.CompileDefs.empty()) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - "COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE"); - return -1; + "COMPILE_DEFINITIONS allowed only in source file signature"); + return false; } - if (!copyFile.empty()) { + if (arguments.CopyFileTo) { this->Makefile->IssueMessage( MessageType::FATAL_ERROR, - "COPY_FILE specified on a srcdir type TRY_COMPILE"); - return -1; + "COPY_FILE allowed only in source file signature"); + return false; } } + // make sure the binary directory exists - cmSystemTools::MakeDirectory(this->BinaryDirectory); + if (useUniqueBinaryDirectory) { + this->BinaryDirectory = + cmStrCat(this->Makefile->GetHomeOutputDirectory(), + "/CMakeFiles/CMakeScratch/TryCompile-XXXXXX"); + cmSystemTools::MakeTempDirectory(this->BinaryDirectory); + } else { + cmSystemTools::MakeDirectory(this->BinaryDirectory); + } // do not allow recursive try Compiles if (this->BinaryDirectory == this->Makefile->GetHomeOutputDirectory()) { @@ -474,7 +460,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, e << "Attempt at a recursive or nested TRY_COMPILE in directory\n" << " " << this->BinaryDirectory << "\n"; this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); - return -1; + return false; } std::string outFileName = this->BinaryDirectory + "/CMakeLists.txt"; @@ -485,9 +471,63 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, cmSystemTools::RemoveFile(ccFile); // Choose sources. - if (!useSources) { - sources.emplace_back(argv[2]); + std::vector<std::string> sources; + if (arguments.Sources) { + sources = std::move(*arguments.Sources); + } else if (arguments.SourceDirectoryOrFile) { + sources.emplace_back(*arguments.SourceDirectoryOrFile); + } + if (arguments.SourceFromContent) { + auto const k = arguments.SourceFromContent->size(); + for (auto i = decltype(k){ 0 }; i < k; i += 2) { + const auto& name = (*arguments.SourceFromContent)[i + 0]; + const auto& content = (*arguments.SourceFromContent)[i + 1]; + auto out = this->WriteSource(name, content, "SOURCE_FROM_CONTENT"); + if (out.empty()) { + return false; + } + sources.emplace_back(std::move(out)); + } + } + if (arguments.SourceFromVar) { + auto const k = arguments.SourceFromVar->size(); + for (auto i = decltype(k){ 0 }; i < k; i += 2) { + const auto& name = (*arguments.SourceFromVar)[i + 0]; + const auto& var = (*arguments.SourceFromVar)[i + 1]; + const auto& content = this->Makefile->GetDefinition(var); + auto out = this->WriteSource(name, content, "SOURCE_FROM_VAR"); + if (out.empty()) { + return false; + } + sources.emplace_back(std::move(out)); + } } + if (arguments.SourceFromFile) { + auto const k = arguments.SourceFromFile->size(); + for (auto i = decltype(k){ 0 }; i < k; i += 2) { + const auto& dst = (*arguments.SourceFromFile)[i + 0]; + const auto& src = (*arguments.SourceFromFile)[i + 1]; + + if (!cmSystemTools::GetFilenamePath(dst).empty()) { + const auto& msg = + cmStrCat("SOURCE_FROM_FILE given invalid filename \"", dst, "\""); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg); + return false; + } + + auto dstPath = cmStrCat(this->BinaryDirectory, "/", dst); + auto const result = cmSystemTools::CopyFileAlways(src, dstPath); + if (!result.IsSuccess()) { + const auto& msg = cmStrCat("SOURCE_FROM_FILE failed to copy \"", src, + "\": ", result.GetString()); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg); + return false; + } + + sources.emplace_back(std::move(dstPath)); + } + } + // TODO: ensure sources is not empty // Detect languages to enable. cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); @@ -508,7 +548,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, err << cmJoin(langs, " "); err << "\nSee project() command to enable other languages."; this->Makefile->IssueMessage(MessageType::FATAL_ERROR, err.str()); - return -1; + return false; } } @@ -535,7 +575,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, << cmSystemTools::GetLastSystemError(); /* clang-format on */ this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); - return -1; + return false; } cmValue def = this->Makefile->GetDefinition("CMAKE_MODULE_PATH"); @@ -575,6 +615,14 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, *cmp0123 == "NEW"_s ? "NEW" : "OLD"); } + /* Set MSVC debug information format policy to match our selection. */ + if (cmValue msvcDebugInformationFormatDefault = + this->Makefile->GetDefinition( + kCMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT)) { + fprintf(fout, "cmake_policy(SET CMP0141 %s)\n", + !msvcDebugInformationFormatDefault->empty() ? "NEW" : "OLD"); + } + /* Set cache/normal variable policy to match outer project. It may affect toolchain files. */ if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0126) != @@ -604,13 +652,22 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } } fprintf(fout, "project(CMAKE_TRY_COMPILE%s)\n", projectLangs.c_str()); - if (cmakeInternal == "ABI") { + if (arguments.CMakeInternal == "ABI") { // This is the ABI detection step, also used for implicit includes. // Erase any include_directories() calls from the toolchain file so // that we do not see them as implicit. Our ABI detection source // does not include any system headers anyway. fprintf(fout, "set_property(DIRECTORY PROPERTY INCLUDE_DIRECTORIES \"\")\n"); + + // The link and compile lines for ABI detection step need to not use + // response files so we can extract implicit includes given to + // the underlying host compiler + if (testLangs.find("CUDA") != testLangs.end()) { + fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_INCLUDES OFF)\n"); + fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES OFF)\n"); + fprintf(fout, "set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_OBJECTS OFF)\n"); + } } fprintf(fout, "set(CMAKE_VERBOSE_MAKEFILE 1)\n"); for (std::string const& li : testLangs) { @@ -702,18 +759,12 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, fprintf(fout, "set(CMAKE_SUPPRESS_REGENERATION 1)\n"); fprintf(fout, "link_directories(${LINK_DIRECTORIES})\n"); // handle any compile flags we need to pass on - if (!compileDefs.empty()) { + if (!arguments.CompileDefs.empty()) { // Pass using bracket arguments to preserve content. fprintf(fout, "add_definitions([==[%s]==])\n", - cmJoin(compileDefs, "]==] [==[").c_str()); + cmJoin(arguments.CompileDefs, "]==] [==[").c_str()); } - /* Use a random file name to avoid rapid creation and deletion - of the same executable name (some filesystems fail on that). */ - snprintf(targetNameBuf, sizeof(targetNameBuf), "cmTC_%05x", - cmSystemTools::RandomSeed() & 0xFFFFF); - targetName = targetNameBuf; - if (!targets.empty()) { std::string fname = "/" + std::string(targetName) + "Targets.cmake"; cmExportTryCompileFileGenerator tcfg(gg, targets, this->Makefile, @@ -725,7 +776,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, this->Makefile->IssueMessage(MessageType::FATAL_ERROR, "could not write export file."); fclose(fout); - return -1; + return false; } fprintf(fout, "\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/%s\")\n\n", fname.c_str()); @@ -769,24 +820,27 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, fprintf(fout, " \"%s\"", si.c_str()); // Add dependencies on any non-temporary sources. - if (si.find("CMakeTmp") == std::string::npos) { + if (!IsTemporary(si)) { this->Makefile->AddCMakeDependFile(si); } } fprintf(fout, ")\n"); - cState.Enabled(testLangs.find("C") != testLangs.end()); - cxxState.Enabled(testLangs.find("CXX") != testLangs.end()); - cudaState.Enabled(testLangs.find("CUDA") != testLangs.end()); - hipState.Enabled(testLangs.find("HIP") != testLangs.end()); - objcState.Enabled(testLangs.find("OBJC") != testLangs.end()); - objcxxState.Enabled(testLangs.find("OBJCXX") != testLangs.end()); + /* Write out the output location of the target we are building */ + std::string perConfigGenex; + if (this->Makefile->GetGlobalGenerator()->IsMultiConfig()) { + perConfigGenex = "_$<UPPER_CASE:$<CONFIG>>"; + } + fprintf(fout, + "file(GENERATE OUTPUT " + "\"${CMAKE_BINARY_DIR}/%s%s_loc\"\n", + targetName.c_str(), perConfigGenex.c_str()); + fprintf(fout, " CONTENT $<TARGET_FILE:%s>)\n", targetName.c_str()); bool warnCMP0067 = false; bool honorStandard = true; - if (cState.DidNone() && cxxState.DidNone() && objcState.DidNone() && - objcxxState.DidNone() && cudaState.DidNone() && hipState.DidNone()) { + if (arguments.LangProps.empty()) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0067)) { case cmPolicies::WARN: warnCMP0067 = this->Makefile->PolicyOptionalWarningEnabled( @@ -811,18 +865,33 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, std::vector<std::string> warnCMP0067Variables; - cState.LoadUnsetPropertyValues(this->Makefile, honorStandard, warnCMP0067, - warnCMP0067Variables); - cxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard, - warnCMP0067, warnCMP0067Variables); - cudaState.LoadUnsetPropertyValues(this->Makefile, honorStandard, - warnCMP0067, warnCMP0067Variables); - hipState.LoadUnsetPropertyValues(this->Makefile, honorStandard, - warnCMP0067, warnCMP0067Variables); - objcState.LoadUnsetPropertyValues(this->Makefile, honorStandard, - warnCMP0067, warnCMP0067Variables); - objcxxState.LoadUnsetPropertyValues(this->Makefile, honorStandard, - warnCMP0067, warnCMP0067Variables); + if (honorStandard || warnCMP0067) { + static std::array<std::string, 6> const possibleLangs{ + { "C", "CXX", "CUDA", "HIP", "OBJC", "OBJCXX" } + }; + static std::array<cm::string_view, 3> const langPropSuffixes{ + { "_STANDARD"_s, "_STANDARD_REQUIRED"_s, "_EXTENSIONS"_s } + }; + for (std::string const& lang : possibleLangs) { + if (testLangs.find(lang) == testLangs.end()) { + continue; + } + for (cm::string_view propSuffix : langPropSuffixes) { + std::string langProp = cmStrCat(lang, propSuffix); + if (!arguments.LangProps.count(langProp)) { + std::string langPropVar = cmStrCat("CMAKE_"_s, langProp); + std::string value = this->Makefile->GetSafeDefinition(langPropVar); + if (warnCMP0067 && !value.empty()) { + value.clear(); + warnCMP0067Variables.emplace_back(langPropVar); + } + if (!value.empty()) { + arguments.LangProps[langProp] = value; + } + } + } + } + } if (!warnCMP0067Variables.empty()) { std::ostringstream w; @@ -838,17 +907,20 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str()); } - cState.WriteProperties(fout, targetName); - cxxState.WriteProperties(fout, targetName); - cudaState.WriteProperties(fout, targetName); - hipState.WriteProperties(fout, targetName); - objcState.WriteProperties(fout, targetName); - objcxxState.WriteProperties(fout, targetName); + for (auto const& p : arguments.LangProps) { + if (p.second.empty()) { + continue; + } + fprintf(fout, "set_property(TARGET %s PROPERTY %s %s)\n", + targetName.c_str(), + cmOutputConverter::EscapeForCMake(p.first).c_str(), + cmOutputConverter::EscapeForCMake(p.second).c_str()); + } - if (!linkOptions.empty()) { + if (!arguments.LinkOptions.empty()) { std::vector<std::string> options; - options.reserve(linkOptions.size()); - for (const auto& option : linkOptions) { + options.reserve(arguments.LinkOptions.size()); + for (const auto& option : arguments.LinkOptions) { options.emplace_back(cmOutputConverter::EscapeForCMake(option)); } @@ -862,15 +934,18 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, } } - if (useOldLinkLibs) { - fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n", - targetName.c_str()); - } else { + if (arguments.LinkLibraries) { + std::string libsToLink = " "; + for (std::string const& i : *arguments.LinkLibraries) { + libsToLink += "\"" + cmTrimWhitespace(i) + "\" "; + } fprintf(fout, "target_link_libraries(%s %s)\n", targetName.c_str(), libsToLink.c_str()); + } else { + fprintf(fout, "target_link_libraries(%s ${LINK_LIBRARIES})\n", + targetName.c_str()); } fclose(fout); - projectName = "CMAKE_TRY_COMPILE"; } // Forward a set of variables to the inner project cache. @@ -917,6 +992,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, vars.insert(kCMAKE_WARN_DEPRECATED); vars.emplace("CMAKE_MSVC_RUNTIME_LIBRARY"_s); vars.emplace("CMAKE_WATCOM_RUNTIME_LIBRARY"_s); + vars.emplace("CMAKE_MSVC_DEBUG_INFORMATION_FORMAT"_s); if (cmValue varListStr = this->Makefile->GetDefinition( kCMAKE_TRY_COMPILE_PLATFORM_VARIABLES)) { @@ -959,13 +1035,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) { vars.erase(kCMAKE_OSX_ARCHITECTURES); std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + *tcArchs; - cmakeFlags.emplace_back(std::move(flag)); + arguments.CMakeFlags.emplace_back(std::move(flag)); } for (std::string const& var : vars) { if (cmValue val = this->Makefile->GetDefinition(var)) { std::string flag = "-D" + var + "=" + *val; - cmakeFlags.emplace_back(std::move(flag)); + arguments.CMakeFlags.emplace_back(std::move(flag)); } } } @@ -975,37 +1051,50 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, for (std::string const& var : ghs_platform_vars) { if (cmValue val = this->Makefile->GetDefinition(var)) { std::string flag = "-D" + var + "=" + "'" + *val + "'"; - cmakeFlags.emplace_back(std::move(flag)); + arguments.CMakeFlags.emplace_back(std::move(flag)); } } } + if (this->Makefile->GetCMakeInstance()->GetDebugTryCompile()) { + auto msg = + cmStrCat("Executing try_compile (", *arguments.CompileResultVariable, + ") in:\n ", this->BinaryDirectory); + this->Makefile->IssueMessage(MessageType::LOG, msg); + } + bool erroroc = cmSystemTools::GetErrorOccurredFlag(); cmSystemTools::ResetErrorOccurredFlag(); std::string output; // actually do the try compile now that everything is setup int res = this->Makefile->TryCompile( sourceDirectory, this->BinaryDirectory, projectName, targetName, - this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL, &cmakeFlags, - output); + this->SrcFileSignature, cmake::NO_BUILD_PARALLEL_LEVEL, + &arguments.CMakeFlags, output); if (erroroc) { cmSystemTools::SetErrorOccurred(); } // set the result var to the return value to indicate success or failure - this->Makefile->AddCacheDefinition(argv[0], (res == 0 ? "TRUE" : "FALSE"), - "Result of TRY_COMPILE", - cmStateEnums::INTERNAL); + if (arguments.NoCache) { + this->Makefile->AddDefinition(*arguments.CompileResultVariable, + (res == 0 ? "TRUE" : "FALSE")); + } else { + this->Makefile->AddCacheDefinition( + *arguments.CompileResultVariable, (res == 0 ? "TRUE" : "FALSE"), + "Result of TRY_COMPILE", cmStateEnums::INTERNAL); + } - if (!outputVariable.empty()) { - this->Makefile->AddDefinition(outputVariable, output); + if (arguments.OutputVariable) { + this->Makefile->AddDefinition(*arguments.OutputVariable, output); } if (this->SrcFileSignature) { std::string copyFileErrorMessage; - this->FindOutputFile(targetName, targetType); + this->FindOutputFile(targetName); - if ((res == 0) && !copyFile.empty()) { + if ((res == 0) && arguments.CopyFileTo) { + std::string const& copyFile = *arguments.CopyFileTo; if (this->OutputFile.empty() || !cmSystemTools::CopyFileAlways(this->OutputFile, copyFile)) { std::ostringstream emsg; @@ -1018,19 +1107,26 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, if (!this->FindErrorMessage.empty()) { emsg << this->FindErrorMessage; } - if (copyFileError.empty()) { + if (!arguments.CopyFileError) { this->Makefile->IssueMessage(MessageType::FATAL_ERROR, emsg.str()); - return -1; + return false; } copyFileErrorMessage = emsg.str(); } } - if (!copyFileError.empty()) { + if (arguments.CopyFileError) { + std::string const& copyFileError = *arguments.CopyFileError; this->Makefile->AddDefinition(copyFileError, copyFileErrorMessage); } } - return res; + return res == 0; +} + +bool cmCoreTryCompile::IsTemporary(std::string const& path) +{ + return ((path.find("CMakeTmp") != std::string::npos) || + (path.find("CMakeScratch") != std::string::npos)); } void cmCoreTryCompile::CleanupFiles(std::string const& binDir) @@ -1039,11 +1135,11 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir) return; } - if (binDir.find("CMakeTmp") == std::string::npos) { + if (!IsTemporary(binDir)) { cmSystemTools::Error( "TRY_COMPILE attempt to remove -rf directory that does not contain " - "CMakeTmp:" + - binDir); + "CMakeTmp or CMakeScratch: \"" + + binDir + "\""); return; } @@ -1089,63 +1185,74 @@ void cmCoreTryCompile::CleanupFiles(std::string const& binDir) } } } + + if (binDir.find("CMakeScratch") != std::string::npos) { + cmSystemTools::RemoveADirectory(binDir); + } } -void cmCoreTryCompile::FindOutputFile(const std::string& targetName, - cmStateEnums::TargetType targetType) +void cmCoreTryCompile::FindOutputFile(const std::string& targetName) { this->FindErrorMessage.clear(); this->OutputFile.clear(); std::string tmpOutputFile = "/"; - if (targetType == cmStateEnums::EXECUTABLE) { - tmpOutputFile += targetName; - tmpOutputFile += - this->Makefile->GetSafeDefinition("CMAKE_EXECUTABLE_SUFFIX"); - } else // if (targetType == cmStateEnums::STATIC_LIBRARY) - { - tmpOutputFile += - this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX"); - tmpOutputFile += targetName; - tmpOutputFile += - this->Makefile->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX"); + tmpOutputFile += targetName; + + if (this->Makefile->GetGlobalGenerator()->IsMultiConfig()) { + tmpOutputFile += "_DEBUG"; + } + tmpOutputFile += "_loc"; + + std::string command = cmStrCat(this->BinaryDirectory, tmpOutputFile); + if (!cmSystemTools::FileExists(command)) { + std::ostringstream emsg; + emsg << "Unable to find the recorded try_compile output location:\n"; + emsg << cmStrCat(" ", command, "\n"); + this->FindErrorMessage = emsg.str(); + return; + } + + std::string outputFileLocation; + cmsys::ifstream ifs(command.c_str()); + cmSystemTools::GetLineFromStream(ifs, outputFileLocation); + if (!cmSystemTools::FileExists(outputFileLocation)) { + std::ostringstream emsg; + emsg << "Recorded try_compile output location doesn't exist:\n"; + emsg << cmStrCat(" ", outputFileLocation, "\n"); + this->FindErrorMessage = emsg.str(); + return; } - // a list of directories where to search for the compilation result - // at first directly in the binary dir - std::vector<std::string> searchDirs; - searchDirs.emplace_back(); - - cmValue config = - this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"); - // if a config was specified try that first - if (cmNonempty(config)) { - std::string tmp = cmStrCat('/', *config); - searchDirs.emplace_back(std::move(tmp)); + this->OutputFile = cmSystemTools::CollapseFullPath(outputFileLocation); +} + +std::string cmCoreTryCompile::WriteSource(std::string const& filename, + std::string const& content, + char const* command) const +{ + if (!cmSystemTools::GetFilenamePath(filename).empty()) { + const auto& msg = + cmStrCat(command, " given invalid filename \"", filename, "\""); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg); + return {}; } - searchDirs.emplace_back("/Debug"); -#if defined(__APPLE__) - std::string app = "/" + targetName + ".app"; - if (cmNonempty(config)) { - std::string tmp = cmStrCat('/', *config, app); - searchDirs.emplace_back(std::move(tmp)); + + auto filepath = cmStrCat(this->BinaryDirectory, "/", filename); + cmsys::ofstream file{ filepath.c_str(), std::ios::out }; + if (!file) { + const auto& msg = + cmStrCat(command, " failed to open \"", filename, "\" for writing"); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg); + return {}; } - std::string tmp = "/Debug" + app; - searchDirs.emplace_back(std::move(tmp)); - searchDirs.emplace_back(std::move(app)); -#endif - searchDirs.emplace_back("/Development"); - for (std::string const& sdir : searchDirs) { - std::string command = cmStrCat(this->BinaryDirectory, sdir, tmpOutputFile); - if (cmSystemTools::FileExists(command)) { - this->OutputFile = cmSystemTools::CollapseFullPath(command); - return; - } + file << content; + if (!file) { + const auto& msg = cmStrCat(command, " failed to write \"", filename, "\""); + this->Makefile->IssueMessage(MessageType::FATAL_ERROR, msg); + return {}; } - std::ostringstream emsg; - emsg << "Unable to find the executable at any of:\n"; - emsg << cmWrap(" " + this->BinaryDirectory, searchDirs, tmpOutputFile, "\n") - << "\n"; - this->FindErrorMessage = emsg.str(); + file.close(); + return filepath; } diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h index 594fd7f..3e1e12c 100644 --- a/Source/cmCoreTryCompile.h +++ b/Source/cmCoreTryCompile.h @@ -4,28 +4,90 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <map> #include <string> #include <vector> -#include "cmCommand.h" +#include <cm/optional> + +#include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" #include "cmStateTypes.h" +class cmMakefile; +template <typename Iter> +class cmRange; + /** \class cmCoreTryCompile * \brief Base class for cmTryCompileCommand and cmTryRunCommand * * cmCoreTryCompile implements the functionality to build a program. * It is the base class for cmTryCompileCommand and cmTryRunCommand. */ -class cmCoreTryCompile : public cmCommand +class cmCoreTryCompile { public: -protected: + cmCoreTryCompile(cmMakefile* mf) + : Makefile(mf) + { + } + + struct Arguments : public ArgumentParser::ParseResult + { + cm::optional<std::string> CompileResultVariable; + cm::optional<std::string> BinaryDirectory; + cm::optional<std::string> SourceDirectoryOrFile; + cm::optional<std::string> ProjectName; + cm::optional<std::string> TargetName; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> Sources; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> + SourceFromContent; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> + SourceFromVar; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> + SourceFromFile; + ArgumentParser::MaybeEmpty<std::vector<std::string>> CMakeFlags{ + 1, "CMAKE_FLAGS" + }; // fake argv[0] + std::vector<std::string> CompileDefs; + cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> + LinkLibraries; + ArgumentParser::MaybeEmpty<std::vector<std::string>> LinkOptions; + std::map<std::string, std::string> LangProps; + std::string CMakeInternal; + cm::optional<std::string> OutputVariable; + cm::optional<std::string> CopyFileTo; + cm::optional<std::string> CopyFileError; + bool NoCache = false; + + // Argument for try_run only. + // Keep in sync with warnings in cmCoreTryCompile::ParseArgs. + cm::optional<std::string> CompileOutputVariable; + cm::optional<std::string> RunOutputVariable; + cm::optional<std::string> RunOutputStdOutVariable; + cm::optional<std::string> RunOutputStdErrVariable; + cm::optional<std::string> RunWorkingDirectory; + cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> RunArgs; + }; + + Arguments ParseArgs(cmRange<std::vector<std::string>::const_iterator> args, + bool isTryRun); + /** - * This is the core code for try compile. It is here so that other - * commands, such as TryRun can access the same logic without - * duplication. + * This is the core code for try compile. It is here so that other commands, + * such as TryRun can access the same logic without duplication. + * + * This function requires at least two \p arguments and will crash if given + * fewer. */ - int TryCompileCode(std::vector<std::string> const& argv, bool isTryRun); + bool TryCompileCode(Arguments& arguments, + cmStateEnums::TargetType targetType); + + /** + * Returns \c true if \p path resides within a CMake temporary directory, + * otherwise returns \c false. + */ + static bool IsTemporary(std::string const& path); /** * This deletes all the files created by TryCompileCode. @@ -39,11 +101,20 @@ protected: TryCompileCode. The result is stored in OutputFile. If nothing is found, the error message is stored in FindErrorMessage. */ - void FindOutputFile(const std::string& targetName, - cmStateEnums::TargetType targetType); + void FindOutputFile(const std::string& targetName); std::string BinaryDirectory; std::string OutputFile; std::string FindErrorMessage; bool SrcFileSignature = false; + cmMakefile* Makefile; + +private: + std::string WriteSource(std::string const& name, std::string const& content, + char const* command) const; + + Arguments ParseArgs( + const cmRange<std::vector<std::string>::const_iterator>& args, + const cmArgumentParser<Arguments>& parser, + std::vector<std::string>& unparsedArguments); }; diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx index 2a52d1a..75c25e3 100644 --- a/Source/cmCreateTestSourceList.cxx +++ b/Source/cmCreateTestSourceList.cxx @@ -87,9 +87,7 @@ bool cmCreateTestSourceList(std::vector<std::string> const& args, func_name = cmSystemTools::GetFilenameWithoutLastExtension(*i); } cmSystemTools::ConvertToUnixSlashes(func_name); - std::replace(func_name.begin(), func_name.end(), ' ', '_'); - std::replace(func_name.begin(), func_name.end(), '/', '_'); - std::replace(func_name.begin(), func_name.end(), ':', '_'); + func_name = cmSystemTools::MakeCidentifier(func_name); bool already_declared = std::find(tests_func_name.begin(), tests_func_name.end(), func_name) != tests_func_name.end(); diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx index 28ee24d..fd6aee1 100644 --- a/Source/cmCurl.cxx +++ b/Source/cmCurl.cxx @@ -34,10 +34,21 @@ std::string cmCurlSetCAInfo(::CURL* curl, const std::string& cafile) { std::string e; + std::string env_ca; if (!cafile.empty()) { ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cafile.c_str()); check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); } + /* Honor the user-configurable OpenSSL environment variables. */ + else if (cmSystemTools::GetEnv("SSL_CERT_FILE", env_ca) && + cmSystemTools::FileExists(env_ca, true)) { + ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, env_ca.c_str()); + check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); + } else if (cmSystemTools::GetEnv("SSL_CERT_DIR", env_ca) && + cmSystemTools::FileIsDirectory(env_ca)) { + ::CURLcode res = ::curl_easy_setopt(curl, CURLOPT_CAPATH, env_ca.c_str()); + check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: "); + } #ifdef CMAKE_FIND_CAFILE # define CMAKE_CAFILE_FEDORA "/etc/pki/tls/certs/ca-bundle.crt" else if (cmSystemTools::FileExists(CMAKE_CAFILE_FEDORA, true)) { diff --git a/Source/cmCxxModuleMapper.cxx b/Source/cmCxxModuleMapper.cxx new file mode 100644 index 0000000..84691c9 --- /dev/null +++ b/Source/cmCxxModuleMapper.cxx @@ -0,0 +1,308 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCxxModuleMapper.h" + +#include <cassert> +#include <cstddef> +#include <set> +#include <sstream> +#include <string> +#include <utility> +#include <vector> + +#include <cm/string_view> +#include <cmext/string_view> + +#include "cmScanDepFormat.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" + +cm::optional<std::string> CxxModuleLocations::BmiGeneratorPathForModule( + std::string const& logical_name) const +{ + if (auto l = this->BmiLocationForModule(logical_name)) { + return this->PathForGenerator(*l); + } + return {}; +} + +namespace { + +std::string CxxModuleMapContentGcc(CxxModuleLocations const& loc, + cmScanDepInfo const& obj) +{ + std::stringstream mm; + + // Documented in GCC's documentation. The format is a series of + // lines with a module name and the associated filename separated + // by spaces. The first line may use `$root` as the module name + // to specify a "repository root". That is used to anchor any + // relative paths present in the file (CMake should never + // generate any). + + // Write the root directory to use for module paths. + mm << "$root " << loc.RootDirectory << "\n"; + + for (auto const& p : obj.Provides) { + if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) { + mm << p.LogicalName << ' ' << *bmi_loc << '\n'; + } + } + for (auto const& r : obj.Requires) { + if (auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName)) { + mm << r.LogicalName << ' ' << *bmi_loc << '\n'; + } + } + + return mm.str(); +} + +std::string CxxModuleMapContentMsvc(CxxModuleLocations const& loc, + cmScanDepInfo const& obj, + CxxModuleUsage const& usages) +{ + std::stringstream mm; + + // A response file of `-reference NAME=PATH` arguments. + + // MSVC's command line only supports a single output. If more than one is + // expected, we cannot make a useful module map file. + if (obj.Provides.size() > 1) { + return {}; + } + + auto flag_for_method = [](LookupMethod method) -> cm::static_string_view { + switch (method) { + case LookupMethod::ByName: + return "-reference"_s; + case LookupMethod::IncludeAngle: + return "-headerUnit:angle"_s; + case LookupMethod::IncludeQuote: + return "-headerUnit:quote"_s; + } + assert(false && "unsupported lookup method"); + return ""_s; + }; + + for (auto const& p : obj.Provides) { + if (p.IsInterface) { + mm << "-interface\n"; + } else { + mm << "-internalPartition\n"; + } + + if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) { + mm << "-ifcOutput " << *bmi_loc << '\n'; + } + } + + std::set<std::string> transitive_usage_directs; + std::set<std::string> transitive_usage_names; + + for (auto const& r : obj.Requires) { + if (auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName)) { + auto flag = flag_for_method(r.Method); + + mm << flag << ' ' << r.LogicalName << '=' << *bmi_loc << "\n"; + transitive_usage_directs.insert(r.LogicalName); + + // Insert transitive usages. + auto transitive_usages = usages.Usage.find(r.LogicalName); + if (transitive_usages != usages.Usage.end()) { + transitive_usage_names.insert(transitive_usages->second.begin(), + transitive_usages->second.end()); + } + } + } + + for (auto const& transitive_name : transitive_usage_names) { + if (transitive_usage_directs.count(transitive_name)) { + continue; + } + + auto module_ref = usages.Reference.find(transitive_name); + if (module_ref != usages.Reference.end()) { + auto flag = flag_for_method(module_ref->second.Method); + mm << flag << ' ' << transitive_name << '=' << module_ref->second.Path + << "\n"; + } + } + + return mm.str(); +} +} + +bool CxxModuleUsage::AddReference(std::string const& logical, + std::string const& loc, LookupMethod method) +{ + auto r = this->Reference.find(logical); + if (r != this->Reference.end()) { + auto& ref = r->second; + + if (ref.Path == loc && ref.Method == method) { + return true; + } + + auto method_name = [](LookupMethod m) -> cm::static_string_view { + switch (m) { + case LookupMethod::ByName: + return "by-name"_s; + case LookupMethod::IncludeAngle: + return "include-angle"_s; + case LookupMethod::IncludeQuote: + return "include-quote"_s; + } + assert(false && "unsupported lookup method"); + return ""_s; + }; + + cmSystemTools::Error(cmStrCat("Disagreement of the location of the '", + logical, + "' module. " + "Location A: '", + ref.Path, "' via ", method_name(ref.Method), + "; " + "Location B: '", + loc, "' via ", method_name(method), ".")); + return false; + } + + auto& ref = this->Reference[logical]; + ref.Path = loc; + ref.Method = method; + + return true; +} + +cm::static_string_view CxxModuleMapExtension( + cm::optional<CxxModuleMapFormat> format) +{ + if (format) { + switch (*format) { + case CxxModuleMapFormat::Gcc: + return ".gcm"_s; + case CxxModuleMapFormat::Msvc: + return ".ifc"_s; + } + } + + return ".bmi"_s; +} + +std::set<std::string> CxxModuleUsageSeed( + CxxModuleLocations const& loc, std::vector<cmScanDepInfo> const& objects, + CxxModuleUsage& usages) +{ + // Track inner usages to populate usages from internal bits. + // + // This is a map of modules that required some other module that was not + // found to those that were not found. + std::map<std::string, std::set<std::string>> internal_usages; + std::set<std::string> unresolved; + + for (cmScanDepInfo const& object : objects) { + // Add references for each of the provided modules. + for (auto const& p : object.Provides) { + if (auto bmi_loc = loc.BmiGeneratorPathForModule(p.LogicalName)) { + // XXX(cxx-modules): How to support header units? + usages.AddReference(p.LogicalName, loc.PathForGenerator(*bmi_loc), + LookupMethod::ByName); + } + } + + // For each requires, pull in what is required. + for (auto const& r : object.Requires) { + // Find transitive usages. + auto transitive_usages = usages.Usage.find(r.LogicalName); + // Find the required name in the current target. + auto bmi_loc = loc.BmiGeneratorPathForModule(r.LogicalName); + + for (auto const& p : object.Provides) { + auto& this_usages = usages.Usage[p.LogicalName]; + + // Add the direct usage. + this_usages.insert(r.LogicalName); + + // Add the transitive usage. + if (transitive_usages != usages.Usage.end()) { + this_usages.insert(transitive_usages->second.begin(), + transitive_usages->second.end()); + } else if (bmi_loc) { + // Mark that we need to update transitive usages later. + internal_usages[p.LogicalName].insert(r.LogicalName); + } + } + + if (bmi_loc) { + usages.AddReference(r.LogicalName, loc.PathForGenerator(*bmi_loc), + r.Method); + } + } + } + + // While we have internal usages to manage. + while (!internal_usages.empty()) { + size_t starting_size = internal_usages.size(); + + // For each internal usage. + for (auto usage = internal_usages.begin(); usage != internal_usages.end(); + /* see end of loop */) { + auto& this_usages = usages.Usage[usage->first]; + + for (auto use = usage->second.begin(); use != usage->second.end(); + /* see end of loop */) { + // Check if this required module uses other internal modules; defer + // if so. + if (internal_usages.count(*use)) { + // Advance the iterator. + ++use; + continue; + } + + auto transitive_usages = usages.Usage.find(*use); + if (transitive_usages != usages.Usage.end()) { + this_usages.insert(transitive_usages->second.begin(), + transitive_usages->second.end()); + } + + // Remove the entry and advance the iterator. + use = usage->second.erase(use); + } + + // Erase the entry if it doesn't have any remaining usages. + if (usage->second.empty()) { + usage = internal_usages.erase(usage); + } else { + ++usage; + } + } + + // Check that at least one usage was resolved. + if (starting_size == internal_usages.size()) { + // Nothing could be resolved this loop; we have a cycle, so record the + // cycle and exit. + for (auto const& usage : internal_usages) { + unresolved.insert(usage.first); + } + break; + } + } + + return unresolved; +} + +std::string CxxModuleMapContent(CxxModuleMapFormat format, + CxxModuleLocations const& loc, + cmScanDepInfo const& obj, + CxxModuleUsage const& usages) +{ + switch (format) { + case CxxModuleMapFormat::Gcc: + return CxxModuleMapContentGcc(loc, obj); + case CxxModuleMapFormat::Msvc: + return CxxModuleMapContentMsvc(loc, obj, usages); + } + + assert(false); + return {}; +} diff --git a/Source/cmCxxModuleMapper.h b/Source/cmCxxModuleMapper.h new file mode 100644 index 0000000..8526a07 --- /dev/null +++ b/Source/cmCxxModuleMapper.h @@ -0,0 +1,85 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <functional> +#include <map> +#include <set> +#include <string> +#include <vector> + +#include <cm/optional> +#include <cmext/string_view> + +#include "cmScanDepFormat.h" + +enum class CxxModuleMapFormat +{ + Gcc, + Msvc, +}; + +struct CxxModuleLocations +{ + // The path from which all relative paths should be computed. If + // this is relative, it is relative to the compiler's working + // directory. + std::string RootDirectory; + + // A function to convert a full path to a path for the generator. + std::function<std::string(std::string const&)> PathForGenerator; + + // Lookup the BMI location of a logical module name. + std::function<cm::optional<std::string>(std::string const&)> + BmiLocationForModule; + + // Returns the generator path (if known) for the BMI given a + // logical module name. + cm::optional<std::string> BmiGeneratorPathForModule( + std::string const& logical_name) const; +}; + +struct CxxModuleReference +{ + // The path to the module file used. + std::string Path; + // How the module was looked up. + LookupMethod Method; +}; + +struct CxxModuleUsage +{ + // The usage requirements for this object. + std::map<std::string, std::set<std::string>> Usage; + + // The references for this object. + std::map<std::string, CxxModuleReference> Reference; + + // Add a reference to a module. + // + // Returns `true` if it matches how it was found previously, `false` if it + // conflicts. + bool AddReference(std::string const& logical, std::string const& loc, + LookupMethod method); +}; + +// Return the extension to use for a given modulemap format. +cm::static_string_view CxxModuleMapExtension( + cm::optional<CxxModuleMapFormat> format); + +// Fill in module usage information for internal usages. +// +// Returns the set of unresolved module usage requirements (these form an +// import cycle). +std::set<std::string> CxxModuleUsageSeed( + CxxModuleLocations const& loc, std::vector<cmScanDepInfo> const& objects, + CxxModuleUsage& usages); + +// Return the contents of the module map in the given format for the +// object file. +std::string CxxModuleMapContent(CxxModuleMapFormat format, + CxxModuleLocations const& loc, + cmScanDepInfo const& obj, + CxxModuleUsage const& usages); diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx index faefcb8..31ee665 100644 --- a/Source/cmDefinePropertyCommand.cxx +++ b/Source/cmDefinePropertyCommand.cxx @@ -8,6 +8,7 @@ #include <cmext/string_view> #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmProperty.h" @@ -51,8 +52,8 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args, // Parse remaining arguments. bool inherited = false; std::string PropertyName; - std::vector<std::string> BriefDocs; - std::vector<std::string> FullDocs; + ArgumentParser::NonEmpty<std::vector<std::string>> BriefDocs; + ArgumentParser::NonEmpty<std::vector<std::string>> FullDocs; std::string initializeFromVariable; cmArgumentParser<void> parser; diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index 3619ade..d466a12 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -17,30 +17,32 @@ #include "cmVersion.h" static const char* cmDocumentationStandardOptions[][2] = { - { "--help,-help,-usage,-h,-H,/?", "Print usage information and exit." }, - { "--version,-version,/V [<f>]", "Print version number and exit." }, - { "--help-full [<f>]", "Print all help manuals and exit." }, - { "--help-manual <man> [<f>]", "Print one help manual and exit." }, - { "--help-manual-list [<f>]", "List help manuals available and exit." }, - { "--help-command <cmd> [<f>]", "Print help for one command and exit." }, - { "--help-command-list [<f>]", + { "-h,-H,--help,-help,-usage,/?", "Print usage information and exit." }, + { "--version,-version,/V [<file>]", "Print version number and exit." }, + { "--help-full [<file>]", "Print all help manuals and exit." }, + { "--help-manual <man> [<file>]", "Print one help manual and exit." }, + { "--help-manual-list [<file>]", "List help manuals available and exit." }, + { "--help-command <cmd> [<file>]", "Print help for one command and exit." }, + { "--help-command-list [<file>]", "List commands with help available and exit." }, - { "--help-commands [<f>]", "Print cmake-commands manual and exit." }, - { "--help-module <mod> [<f>]", "Print help for one module and exit." }, - { "--help-module-list [<f>]", "List modules with help available and exit." }, - { "--help-modules [<f>]", "Print cmake-modules manual and exit." }, - { "--help-policy <cmp> [<f>]", "Print help for one policy and exit." }, - { "--help-policy-list [<f>]", + { "--help-commands [<file>]", "Print cmake-commands manual and exit." }, + { "--help-module <mod> [<file>]", "Print help for one module and exit." }, + { "--help-module-list [<file>]", + "List modules with help available and exit." }, + { "--help-modules [<file>]", "Print cmake-modules manual and exit." }, + { "--help-policy <cmp> [<file>]", "Print help for one policy and exit." }, + { "--help-policy-list [<file>]", "List policies with help available and exit." }, - { "--help-policies [<f>]", "Print cmake-policies manual and exit." }, - { "--help-property <prop> [<f>]", "Print help for one property and exit." }, - { "--help-property-list [<f>]", + { "--help-policies [<file>]", "Print cmake-policies manual and exit." }, + { "--help-property <prop> [<file>]", + "Print help for one property and exit." }, + { "--help-property-list [<file>]", "List properties with help available and exit." }, - { "--help-properties [<f>]", "Print cmake-properties manual and exit." }, - { "--help-variable var [<f>]", "Print help for one variable and exit." }, - { "--help-variable-list [<f>]", + { "--help-properties [<file>]", "Print cmake-properties manual and exit." }, + { "--help-variable var [<file>]", "Print help for one variable and exit." }, + { "--help-variable-list [<file>]", "List variables with help available and exit." }, - { "--help-variables [<f>]", "Print cmake-variables manual and exit." }, + { "--help-variables [<file>]", "Print cmake-variables manual and exit." }, { nullptr, nullptr } }; diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 222ea80..7fbd826 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -47,7 +47,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, return false; } - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { std::vector<std::vector<std::string>> Commands; std::string OutputVariable; @@ -95,14 +95,10 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, .Bind("COMMAND_ERROR_IS_FATAL"_s, &Arguments::CommandErrorIsFatal); std::vector<std::string> unparsedArguments; - std::vector<std::string> keywordsMissingValue; - Arguments const arguments = - parser.Parse(args, &unparsedArguments, &keywordsMissingValue); + Arguments const arguments = parser.Parse(args, &unparsedArguments); - if (!keywordsMissingValue.empty()) { - status.SetError(" called with no value for " + - keywordsMissingValue.front() + "."); - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } if (!unparsedArguments.empty()) { status.SetError(" given unknown argument \"" + unparsedArguments.front() + diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h index 0feaedf..ced3548 100644 --- a/Source/cmExecutionStatus.h +++ b/Source/cmExecutionStatus.h @@ -5,6 +5,7 @@ #include <cmConfigure.h> // IWYU pragma: keep #include <string> +#include <vector> class cmMakefile; @@ -27,8 +28,21 @@ public: void SetError(std::string const& e) { this->Error = e; } std::string const& GetError() const { return this->Error; } - void SetReturnInvoked() { this->ReturnInvoked = true; } + void SetReturnInvoked() + { + this->Variables.clear(); + this->ReturnInvoked = true; + } + void SetReturnInvoked(std::vector<std::string> variables) + { + this->Variables = std::move(variables); + this->ReturnInvoked = true; + } bool GetReturnInvoked() const { return this->ReturnInvoked; } + const std::vector<std::string>& GetReturnVariables() const + { + return this->Variables; + } void SetBreakInvoked() { this->BreakInvoked = true; } bool GetBreakInvoked() const { return this->BreakInvoked; } @@ -46,4 +60,5 @@ private: bool BreakInvoked = false; bool ContinueInvoked = false; bool NestedError = false; + std::vector<std::string> Variables; }; diff --git a/Source/cmExperimental.cxx b/Source/cmExperimental.cxx new file mode 100644 index 0000000..922b53f --- /dev/null +++ b/Source/cmExperimental.cxx @@ -0,0 +1,63 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmExperimental.h" + +#include <cassert> +#include <cstddef> +#include <string> + +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmValue.h" + +namespace { + +/* + * The `Uuid` fields of these objects should change periodically. + * Search for other instances to keep the documentation and test suite + * up-to-date. + */ + +struct FeatureData +{ + std::string const Uuid; + std::string const Variable; + std::string const Description; + bool Warned; +} LookupTable[] = { + // CxxModuleCMakeApi + { "3c375311-a3c9-4396-a187-3227ef642046", + "CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API", + "CMake's C++ module support is experimental. It is meant only for " + "experimentation and feedback to CMake developers.", + false }, +}; +static_assert(sizeof(LookupTable) / sizeof(LookupTable[0]) == + static_cast<size_t>(cmExperimental::Feature::Sentinel), + "Experimental feature lookup table mismatch"); + +FeatureData& DataForFeature(cmExperimental::Feature f) +{ + assert(f != cmExperimental::Feature::Sentinel); + return LookupTable[static_cast<size_t>(f)]; +} +} + +bool cmExperimental::HasSupportEnabled(cmMakefile const& mf, Feature f) +{ + bool enabled = false; + auto& data = DataForFeature(f); + + auto value = mf.GetDefinition(data.Variable); + if (value == data.Uuid) { + enabled = true; + } + + if (enabled && !data.Warned) { + mf.IssueMessage(MessageType::AUTHOR_WARNING, data.Description); + data.Warned = true; + } + + return enabled; +} diff --git a/Source/cmExperimental.h b/Source/cmExperimental.h new file mode 100644 index 0000000..26e0d17 --- /dev/null +++ b/Source/cmExperimental.h @@ -0,0 +1,21 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +class cmMakefile; + +class cmExperimental +{ +public: + enum class Feature + { + CxxModuleCMakeApi, + + Sentinel, + }; + + static bool HasSupportEnabled(cmMakefile const& mf, Feature f); +}; diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index 6ce0c98..ed199ea 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -9,10 +9,13 @@ #include <sstream> #include <utility> +#include <cm/string_view> #include <cmext/algorithm> +#include <cmext/string_view> #include "cmExportSet.h" #include "cmFileSet.h" +#include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" @@ -23,6 +26,7 @@ #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" +#include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetExport.h" #include "cmValue.h" @@ -139,11 +143,18 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os) this->GenerateTargetFileSets(gte, os); } + this->GenerateCxxModuleInformation(os); + // Generate import file content for each configuration. for (std::string const& c : this->Configurations) { this->GenerateImportConfig(os, c); } + // Generate import file content for each configuration. + for (std::string const& c : this->Configurations) { + this->GenerateImportCxxModuleConfigTargetInclusion(c); + } + this->GenerateMissingTargetsCheckCode(os); return true; @@ -382,6 +393,21 @@ std::string cmExportBuildFileGenerator::GetFileSetDirectories( std::any_of(directoryEntries.begin(), directoryEntries.end(), EntryIsContextSensitive); + auto const& type = fileSet->GetType(); + // C++ modules do not support interface file sets which are dependent upon + // the configuration. + if (contextSensitive && + (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) { + auto* mf = this->LG->GetMakefile(); + std::ostringstream e; + e << "The \"" << gte->GetName() << "\" target's interface file set \"" + << fileSet->GetName() << "\" of type \"" << type + << "\" contains context-sensitive base directory entries which is not " + "supported."; + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return std::string{}; + } + for (auto const& directory : directories) { auto dest = cmOutputConverter::EscapeForCMake( directory, cmOutputConverter::WrapQuotes::NoWrap); @@ -427,6 +453,21 @@ std::string cmExportBuildFileGenerator::GetFileSetFiles(cmGeneratorTarget* gte, std::any_of(fileEntries.begin(), fileEntries.end(), EntryIsContextSensitive); + auto const& type = fileSet->GetType(); + // C++ modules do not support interface file sets which are dependent upon + // the configuration. + if (contextSensitive && + (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) { + auto* mf = this->LG->GetMakefile(); + std::ostringstream e; + e << "The \"" << gte->GetName() << "\" target's interface file set \"" + << fileSet->GetName() << "\" of type \"" << type + << "\" contains context-sensitive file entries which is not " + "supported."; + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return std::string{}; + } + for (auto const& it : files) { for (auto const& filename : it.second) { auto escapedFile = cmOutputConverter::EscapeForCMake( @@ -447,3 +488,60 @@ std::string cmExportBuildFileGenerator::GetFileSetFiles(cmGeneratorTarget* gte, return cmJoin(resultVector, " "); } + +std::string cmExportBuildFileGenerator::GetCxxModulesDirectory() const +{ + return this->CxxModulesDirectory; +} + +void cmExportBuildFileGenerator::GenerateCxxModuleConfigInformation( + std::ostream& os) const +{ + const char* opt = ""; + if (this->Configurations.size() > 1) { + // With more than one configuration, each individual file is optional. + opt = " OPTIONAL"; + } + + // Generate import file content for each configuration. + for (std::string c : this->Configurations) { + if (c.empty()) { + c = "noconfig"; + } + os << "include(\"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-" << c << ".cmake\"" + << opt << ")\n"; + } +} + +bool cmExportBuildFileGenerator::GenerateImportCxxModuleConfigTargetInclusion( + std::string config) const +{ + auto cxx_modules_dirname = this->GetCxxModulesDirectory(); + if (cxx_modules_dirname.empty()) { + return true; + } + + if (config.empty()) { + config = "noconfig"; + } + + std::string fileName = cmStrCat(this->FileDir, '/', cxx_modules_dirname, + "/cxx-modules-", config, ".cmake"); + + cmGeneratedFileStream os(fileName, true); + if (!os) { + std::string se = cmSystemTools::GetLastSystemError(); + std::ostringstream e; + e << "cannot write to file \"" << fileName << "\": " << se; + cmSystemTools::Error(e.str()); + return false; + } + os.SetCopyIfDifferent(true); + + for (auto const* tgt : this->ExportedTargets) { + os << "include(\"${CMAKE_CURRENT_LIST_DIR}/target-" << tgt->GetExportName() + << '-' << config << ".cmake\")\n"; + } + + return true; +} diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h index 5681e8f..4636196 100644 --- a/Source/cmExportBuildFileGenerator.h +++ b/Source/cmExportBuildFileGenerator.h @@ -47,6 +47,16 @@ public: } void SetExportSet(cmExportSet*); + /** Set the name of the C++ module directory. */ + void SetCxxModuleDirectory(std::string cxx_module_dir) + { + this->CxxModulesDirectory = std::move(cxx_module_dir); + } + const std::string& GetCxxModuleDirectory() const + { + return this->CxxModulesDirectory; + } + /** Set whether to append generated code to the output file. */ void SetAppendMode(bool append) { this->AppendMode = append; } @@ -81,6 +91,10 @@ protected: std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te) override; + std::string GetCxxModulesDirectory() const override; + void GenerateCxxModuleConfigInformation(std::ostream&) const override; + bool GenerateImportCxxModuleConfigTargetInclusion(std::string) const; + std::pair<std::vector<std::string>, std::string> FindBuildExportInfo( cmGlobalGenerator* gg, const std::string& name); @@ -88,4 +102,6 @@ protected: cmExportSet* ExportSet; std::vector<cmGeneratorTarget*> Exports; cmLocalGenerator* LG; + // The directory for C++ module information. + std::string CxxModulesDirectory; }; diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 63440a3..a58f2b7 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -7,13 +7,15 @@ #include <utility> #include <cm/memory> -#include <cmext/algorithm> +#include <cm/optional> #include <cmext/string_view> #include "cmsys/RegularExpression.hxx" #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" #include "cmExecutionStatus.h" +#include "cmExperimental.h" #include "cmExportBuildAndroidMKGenerator.h" #include "cmExportBuildFileGenerator.h" #include "cmExportSet.h" @@ -57,10 +59,11 @@ bool cmExportCommand(std::vector<std::string> const& args, struct Arguments { std::string ExportSetName; - std::vector<std::string> Targets; + cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> Targets; std::string Namespace; std::string Filename; std::string AndroidMKFile; + std::string CxxModulesDirectory; bool Append = false; bool ExportOld = false; }; @@ -69,6 +72,12 @@ bool cmExportCommand(std::vector<std::string> const& args, .Bind("NAMESPACE"_s, &Arguments::Namespace) .Bind("FILE"_s, &Arguments::Filename); + bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled( + status.GetMakefile(), cmExperimental::Feature::CxxModuleCMakeApi); + if (supportCxx20FileSetTypes) { + parser.Bind("CXX_MODULES_DIRECTORY"_s, &Arguments::CxxModulesDirectory); + } + if (args[0] == "EXPORT") { parser.Bind("EXPORT"_s, &Arguments::ExportSetName); } else { @@ -79,9 +88,7 @@ bool cmExportCommand(std::vector<std::string> const& args, } std::vector<std::string> unknownArgs; - std::vector<std::string> keywordsMissingValue; - Arguments const arguments = - parser.Parse(args, &unknownArgs, &keywordsMissingValue); + Arguments const arguments = parser.Parse(args, &unknownArgs); if (!unknownArgs.empty()) { status.SetError("Unknown argument: \"" + unknownArgs.front() + "\"."); @@ -145,9 +152,8 @@ bool cmExportCommand(std::vector<std::string> const& args, return false; } exportSet = &it->second; - } else if (!arguments.Targets.empty() || - cm::contains(keywordsMissingValue, "TARGETS")) { - for (std::string const& currentTarget : arguments.Targets) { + } else if (arguments.Targets) { + for (std::string const& currentTarget : *arguments.Targets) { if (mf.IsAlias(currentTarget)) { std::ostringstream e; e << "given ALIAS target \"" << currentTarget @@ -214,6 +220,7 @@ bool cmExportCommand(std::vector<std::string> const& args, } ebfg->SetExportFile(fname.c_str()); ebfg->SetNamespace(arguments.Namespace); + ebfg->SetCxxModuleDirectory(arguments.CxxModulesDirectory); ebfg->SetAppendMode(arguments.Append); if (exportSet != nullptr) { ebfg->SetExportSet(exportSet); diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 5a33349..50bc78c 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -939,13 +939,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // Isolate the file policy level. // Support CMake versions as far back as 2.6 but also support using NEW - // policy settings for up to CMake 3.22 (this upper limit may be reviewed + // policy settings for up to CMake 3.23 (this upper limit may be reviewed // and increased from time to time). This reduces the opportunity for CMake // warnings when an older export file is later used with newer CMake // versions. /* clang-format off */ os << "cmake_policy(PUSH)\n" - << "cmake_policy(VERSION 2.8.3...3.22)\n"; + << "cmake_policy(VERSION 2.8.3...3.23)\n"; /* clang-format on */ } @@ -1095,6 +1095,10 @@ void cmExportFileGenerator::GenerateImportTargetCode( << " PROPERTY IMPORTED_NO_SYSTEM 1)\n"; } + if (target->GetPropertyAsBool("EXPORT_NO_SYSTEM")) { + os << "set_property(TARGET " << targetName << " PROPERTY SYSTEM 0)\n"; + } + os << "\n"; } @@ -1308,3 +1312,28 @@ void cmExportFileGenerator::GenerateTargetFileSets(cmGeneratorTarget* gte, os << " )\nendif()\n\n"; } } + +void cmExportFileGenerator::GenerateCxxModuleInformation(std::ostream& os) +{ + auto const cxx_module_dirname = this->GetCxxModulesDirectory(); + if (cxx_module_dirname.empty()) { + return; + } + + // Write the include. + os << "# Include C++ module properties\n" + << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << cxx_module_dirname + << "/cxx-modules.cmake\")\n\n"; + + // Get the path to the file we're going to write. + std::string path = this->MainImportFile; + path = cmSystemTools::GetFilenamePath(path); + auto trampoline_path = + cmStrCat(path, '/', cxx_module_dirname, "/cxx-modules.cmake"); + + // Include all configuration-specific include files. + cmGeneratedFileStream ap(trampoline_path, true); + ap.SetCopyIfDifferent(true); + + this->GenerateCxxModuleConfigInformation(ap); +} diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h index d27a555..fdda878 100644 --- a/Source/cmExportFileGenerator.h +++ b/Source/cmExportFileGenerator.h @@ -182,6 +182,8 @@ protected: void GenerateTargetFileSets(cmGeneratorTarget* gte, std::ostream& os, cmTargetExport* te = nullptr); + void GenerateCxxModuleInformation(std::ostream& os); + virtual std::string GetFileSetDirectories(cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te) = 0; @@ -226,4 +228,7 @@ private: virtual std::string InstallNameDir(cmGeneratorTarget const* target, const std::string& config) = 0; + + virtual std::string GetCxxModulesDirectory() const = 0; + virtual void GenerateCxxModuleConfigInformation(std::ostream& os) const = 0; }; diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx index 4e4f8a1..d53254d 100644 --- a/Source/cmExportInstallAndroidMKGenerator.cxx +++ b/Source/cmExportInstallAndroidMKGenerator.cxx @@ -35,8 +35,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode( for (size_t n = 0; n < numDotDot; n++) { path += "/.."; } - os << "_IMPORT_PREFIX := " - << "$(LOCAL_PATH)" << path << "\n\n"; + os << "_IMPORT_PREFIX := $(LOCAL_PATH)" << path << "\n\n"; for (std::unique_ptr<cmTargetExport> const& te : this->IEGen->GetExportSet()->GetTargetExports()) { // Collect import properties for this target. diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index adccdfe..195737b 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -7,6 +7,9 @@ #include <sstream> #include <utility> +#include <cm/string_view> +#include <cmext/string_view> + #include "cmExportSet.h" #include "cmFileSet.h" #include "cmGeneratedFileStream.h" @@ -18,6 +21,7 @@ #include "cmInstallTargetGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" +#include "cmMessageType.h" #include "cmOutputConverter.h" #include "cmPolicies.h" #include "cmStateTypes.h" @@ -162,10 +166,20 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os) this->LoadConfigFiles(os); + bool result = true; + + this->GenerateCxxModuleInformation(os); + if (requiresConfigFiles) { + for (std::string const& c : this->Configurations) { + if (!this->GenerateImportCxxModuleConfigTargetInclusion(c)) { + result = false; + } + } + } + this->CleanupTemporaryVariables(os); this->GenerateImportedFileCheckLoop(os); - bool result = true; // Generate an import file for each configuration. // Don't do this if we only export INTERFACE_LIBRARY targets. if (requiresConfigFiles) { @@ -422,7 +436,10 @@ void cmExportInstallFileGenerator::SetImportLocationProperty( // Append the installed file name. if (target->IsAppBundleOnApple()) { value += cmInstallTargetGenerator::GetInstallFilename(target, config); - value += ".app/Contents/MacOS/"; + value += ".app/"; + if (!target->Makefile->PlatformIsAppleEmbedded()) { + value += "Contents/MacOS/"; + } value += cmInstallTargetGenerator::GetInstallFilename(target, config); } else { value += cmInstallTargetGenerator::GetInstallFilename( @@ -562,6 +579,21 @@ std::string cmExportInstallFileGenerator::GetFileSetDirectories( cge->Evaluate(gte->LocalGenerator, config, gte), cmOutputConverter::WrapQuotes::NoWrap)); + auto const& type = fileSet->GetType(); + // C++ modules do not support interface file sets which are dependent upon + // the configuration. + if (cge->GetHadContextSensitiveCondition() && + (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) { + auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile(); + std::ostringstream e; + e << "The \"" << gte->GetName() << "\" target's interface file set \"" + << fileSet->GetName() << "\" of type \"" << type + << "\" contains context-sensitive base file entries which is not " + "supported."; + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return std::string{}; + } + if (cge->GetHadContextSensitiveCondition() && configs.size() != 1) { resultVector.push_back( cmStrCat("\"$<$<CONFIG:", config, ">:", dest, ">\"")); @@ -610,6 +642,21 @@ std::string cmExportInstallFileGenerator::GetFileSetFiles( std::any_of(fileEntries.begin(), fileEntries.end(), EntryIsContextSensitive); + auto const& type = fileSet->GetType(); + // C++ modules do not support interface file sets which are dependent upon + // the configuration. + if (contextSensitive && + (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s)) { + auto* mf = this->IEGen->GetLocalGenerator()->GetMakefile(); + std::ostringstream e; + e << "The \"" << gte->GetName() << "\" target's interface file set \"" + << fileSet->GetName() << "\" of type \"" << type + << "\" contains context-sensitive base file entries which is not " + "supported."; + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + return std::string{}; + } + for (auto const& it : files) { auto prefix = it.first.empty() ? "" : cmStrCat(it.first, '/'); for (auto const& filename : it.second) { @@ -635,3 +682,65 @@ std::string cmExportInstallFileGenerator::GetFileSetFiles( return cmJoin(resultVector, " "); } + +std::string cmExportInstallFileGenerator::GetCxxModulesDirectory() const +{ + return IEGen->GetCxxModuleDirectory(); +} + +void cmExportInstallFileGenerator::GenerateCxxModuleConfigInformation( + std::ostream& os) const +{ + // Now load per-configuration properties for them. + /* clang-format off */ + os << "# Load information for each installed configuration.\n" + "file(GLOB _cmake_cxx_module_includes \"${CMAKE_CURRENT_LIST_DIR}/cxx-modules-*.cmake\")\n" + "foreach(_cmake_cxx_module_include IN LISTS _cmake_cxx_module_includes)\n" + " include(\"${_cmake_cxx_module_include}\")\n" + "endforeach()\n" + "unset(_cmake_cxx_module_include)\n" + "unset(_cmake_cxx_module_includes)\n"; + /* clang-format on */ +} + +bool cmExportInstallFileGenerator:: + GenerateImportCxxModuleConfigTargetInclusion(std::string const& config) +{ + auto cxx_modules_dirname = this->GetCxxModulesDirectory(); + if (cxx_modules_dirname.empty()) { + return true; + } + + std::string filename_config = config; + if (filename_config.empty()) { + filename_config = "noconfig"; + } + + std::string const dest = + cmStrCat(this->FileDir, '/', cxx_modules_dirname, '/'); + std::string fileName = + cmStrCat(dest, "cxx-modules-", filename_config, ".cmake"); + + cmGeneratedFileStream os(fileName, true); + if (!os) { + std::string se = cmSystemTools::GetLastSystemError(); + std::ostringstream e; + e << "cannot write to file \"" << fileName << "\": " << se; + cmSystemTools::Error(e.str()); + return false; + } + os.SetCopyIfDifferent(true); + + // Record this per-config import file. + this->ConfigCxxModuleFiles[config] = fileName; + + auto& prop_files = this->ConfigCxxModuleTargetFiles[config]; + for (auto const* tgt : this->ExportedTargets) { + auto prop_filename = cmStrCat("target-", tgt->GetExportName(), '-', + filename_config, ".cmake"); + prop_files.emplace_back(cmStrCat(dest, prop_filename)); + os << "include(\"${CMAKE_CURRENT_LIST_DIR}/" << prop_filename << "\")\n"; + } + + return true; +} diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h index 86fb505..e073a31 100644 --- a/Source/cmExportInstallFileGenerator.h +++ b/Source/cmExportInstallFileGenerator.h @@ -50,6 +50,23 @@ public: return this->ConfigImportFiles; } + /** Get the per-config C++ module file generated for each configuration. + This maps from the configuration name to the file temporary location + for installation. */ + std::map<std::string, std::string> const& GetConfigCxxModuleFiles() + { + return this->ConfigCxxModuleFiles; + } + + /** Get the per-config C++ module file generated for each configuration. + This maps from the configuration name to the file temporary location + for installation for each target in the export set. */ + std::map<std::string, std::vector<std::string>> const& + GetConfigCxxModuleTargetFiles() + { + return this->ConfigCxxModuleTargetFiles; + } + /** Compute the globbing expression used to load per-config import files from the main file. */ std::string GetConfigImportFileGlob(); @@ -100,8 +117,16 @@ protected: std::string GetFileSetFiles(cmGeneratorTarget* gte, cmFileSet* fileSet, cmTargetExport* te) override; + std::string GetCxxModulesDirectory() const override; + void GenerateCxxModuleConfigInformation(std::ostream&) const override; + bool GenerateImportCxxModuleConfigTargetInclusion(std::string const&); + cmInstallExportGenerator* IEGen; // The import file generated for each configuration. std::map<std::string, std::string> ConfigImportFiles; + // The C++ module property file generated for each configuration. + std::map<std::string, std::string> ConfigCxxModuleFiles; + // The C++ module property target files generated for each configuration. + std::map<std::string, std::vector<std::string>> ConfigCxxModuleTargetFiles; }; diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h index 1dd8a20..5c34fad 100644 --- a/Source/cmExportTryCompileFileGenerator.h +++ b/Source/cmExportTryCompileFileGenerator.h @@ -55,6 +55,9 @@ protected: std::string GetFileSetFiles(cmGeneratorTarget* target, cmFileSet* fileSet, cmTargetExport* te) override; + std::string GetCxxModulesDirectory() const override { return {}; } + void GenerateCxxModuleConfigInformation(std::ostream&) const override {} + private: std::string FindTargets(const std::string& prop, const cmGeneratorTarget* tgt, diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index dd0540c..0581802 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -27,6 +27,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmInstallCxxModuleBmiGenerator.h" #include "cmInstallDirectoryGenerator.h" #include "cmInstallExportGenerator.h" #include "cmInstallFileSetGenerator.h" @@ -1092,6 +1093,21 @@ Json::Value DirectoryObject::DumpInstaller(cmInstallGenerator* gen) if (installFileSet->GetOptional()) { installer["isOptional"] = true; } + } else if (auto* cxxModuleBmi = + dynamic_cast<cmInstallCxxModuleBmiGenerator*>(gen)) { + installer["type"] = "cxxModuleBmi"; + installer["destination"] = cxxModuleBmi->GetDestination(this->Config); + + auto const* target = cxxModuleBmi->GetTarget(); + installer["cxxModuleBmiTarget"] = Json::objectValue; + installer["cxxModuleBmiTarget"]["id"] = TargetId(target, this->TopBuild); + installer["cxxModuleBmiTarget"]["index"] = this->TargetIndexMap[target]; + + // FIXME: Parse FilePermissions. + // FIXME: Parse MessageLevel. + if (cxxModuleBmi->GetOptional()) { + installer["isOptional"] = true; + } } // Add fields common to all install generators. diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 3c234a6..421ff12 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -28,8 +28,8 @@ #include "cm_sys_stat.h" -#include "cmAlgorithms.h" #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" #include "cmCMakePath.h" #include "cmCryptoHash.h" #include "cmELF.h" @@ -172,7 +172,8 @@ bool HandleReadCommand(std::vector<std::string> const& args, .Bind("LIMIT"_s, &Arguments::Limit) .Bind("HEX"_s, &Arguments::Hex); - Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3)); + Arguments const arguments = parser.Parse(cmMakeRange(args).advance(3), + /*unparsedArguments=*/nullptr); std::string fileName = fileNameArg; if (!cmsys::SystemTools::FileIsFullPath(fileName)) { @@ -959,42 +960,34 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args, { // Evaluate arguments. std::string file; - std::string oldRPath; - std::string newRPath; + cm::optional<std::string> oldRPath; + cm::optional<std::string> newRPath; bool removeEnvironmentRPath = false; cmArgumentParser<void> parser; std::vector<std::string> unknownArgs; - std::vector<std::string> missingArgs; - std::vector<std::string> parsedArgs; parser.Bind("FILE"_s, file) .Bind("OLD_RPATH"_s, oldRPath) .Bind("NEW_RPATH"_s, newRPath) .Bind("INSTALL_REMOVE_ENVIRONMENT_RPATH"_s, removeEnvironmentRPath); - parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs, - &parsedArgs); + ArgumentParser::ParseResult parseResult = + parser.Parse(cmMakeRange(args).advance(1), &unknownArgs); if (!unknownArgs.empty()) { status.SetError( cmStrCat("RPATH_CHANGE given unknown argument ", unknownArgs.front())); return false; } - if (!missingArgs.empty()) { - status.SetError(cmStrCat("RPATH_CHANGE \"", missingArgs.front(), - "\" argument not given value.")); - return false; + if (parseResult.MaybeReportError(status.GetMakefile())) { + return true; } if (file.empty()) { status.SetError("RPATH_CHANGE not given FILE option."); return false; } - if (oldRPath.empty() && - std::find(parsedArgs.begin(), parsedArgs.end(), "OLD_RPATH") == - parsedArgs.end()) { + if (!oldRPath) { status.SetError("RPATH_CHANGE not given OLD_RPATH option."); return false; } - if (newRPath.empty() && - std::find(parsedArgs.begin(), parsedArgs.end(), "NEW_RPATH") == - parsedArgs.end()) { + if (!newRPath) { status.SetError("RPATH_CHANGE not given NEW_RPATH option."); return false; } @@ -1008,17 +1001,17 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args, std::string emsg; bool changed; - if (!cmSystemTools::ChangeRPath(file, oldRPath, newRPath, + if (!cmSystemTools::ChangeRPath(file, *oldRPath, *newRPath, removeEnvironmentRPath, &emsg, &changed)) { status.SetError(cmStrCat("RPATH_CHANGE could not write new RPATH:\n ", - newRPath, "\nto the file:\n ", file, "\n", + *newRPath, "\nto the file:\n ", file, "\n", emsg)); success = false; } if (success) { if (changed) { std::string message = - cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"'); + cmStrCat("Set runtime path of \"", file, "\" to \"", *newRPath, '"'); status.GetMakefile().DisplayStatus(message, -1); } ft.Store(file); @@ -1031,31 +1024,25 @@ bool HandleRPathSetCommand(std::vector<std::string> const& args, { // Evaluate arguments. std::string file; - std::string newRPath; + cm::optional<std::string> newRPath; cmArgumentParser<void> parser; std::vector<std::string> unknownArgs; - std::vector<std::string> missingArgs; - std::vector<std::string> parsedArgs; parser.Bind("FILE"_s, file).Bind("NEW_RPATH"_s, newRPath); - parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs, - &parsedArgs); + ArgumentParser::ParseResult parseResult = + parser.Parse(cmMakeRange(args).advance(1), &unknownArgs); if (!unknownArgs.empty()) { status.SetError(cmStrCat("RPATH_SET given unrecognized argument \"", unknownArgs.front(), "\".")); return false; } - if (!missingArgs.empty()) { - status.SetError(cmStrCat("RPATH_SET \"", missingArgs.front(), - "\" argument not given value.")); - return false; + if (parseResult.MaybeReportError(status.GetMakefile())) { + return true; } if (file.empty()) { status.SetError("RPATH_SET not given FILE option."); return false; } - if (newRPath.empty() && - std::find(parsedArgs.begin(), parsedArgs.end(), "NEW_RPATH") == - parsedArgs.end()) { + if (!newRPath) { status.SetError("RPATH_SET not given NEW_RPATH option."); return false; } @@ -1069,16 +1056,16 @@ bool HandleRPathSetCommand(std::vector<std::string> const& args, std::string emsg; bool changed; - if (!cmSystemTools::SetRPath(file, newRPath, &emsg, &changed)) { + if (!cmSystemTools::SetRPath(file, *newRPath, &emsg, &changed)) { status.SetError(cmStrCat("RPATH_SET could not write new RPATH:\n ", - newRPath, "\nto the file:\n ", file, "\n", + *newRPath, "\nto the file:\n ", file, "\n", emsg)); success = false; } if (success) { if (changed) { std::string message = - cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"'); + cmStrCat("Set runtime path of \"", file, "\" to \"", *newRPath, '"'); status.GetMakefile().DisplayStatus(message, -1); } ft.Store(file); @@ -1093,18 +1080,16 @@ bool HandleRPathRemoveCommand(std::vector<std::string> const& args, std::string file; cmArgumentParser<void> parser; std::vector<std::string> unknownArgs; - std::vector<std::string> missingArgs; parser.Bind("FILE"_s, file); - parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs); + ArgumentParser::ParseResult parseResult = + parser.Parse(cmMakeRange(args).advance(1), &unknownArgs); if (!unknownArgs.empty()) { status.SetError( cmStrCat("RPATH_REMOVE given unknown argument ", unknownArgs.front())); return false; } - if (!missingArgs.empty()) { - status.SetError(cmStrCat("RPATH_REMOVE \"", missingArgs.front(), - "\" argument not given value.")); - return false; + if (parseResult.MaybeReportError(status.GetMakefile())) { + return true; } if (file.empty()) { status.SetError("RPATH_REMOVE not given FILE option."); @@ -1141,31 +1126,25 @@ bool HandleRPathCheckCommand(std::vector<std::string> const& args, { // Evaluate arguments. std::string file; - std::string rpath; + cm::optional<std::string> rpath; cmArgumentParser<void> parser; std::vector<std::string> unknownArgs; - std::vector<std::string> missingArgs; - std::vector<std::string> parsedArgs; parser.Bind("FILE"_s, file).Bind("RPATH"_s, rpath); - parser.Parse(cmMakeRange(args).advance(1), &unknownArgs, &missingArgs, - &parsedArgs); + ArgumentParser::ParseResult parseResult = + parser.Parse(cmMakeRange(args).advance(1), &unknownArgs); if (!unknownArgs.empty()) { status.SetError( cmStrCat("RPATH_CHECK given unknown argument ", unknownArgs.front())); return false; } - if (!missingArgs.empty()) { - status.SetError(cmStrCat("RPATH_CHECK \"", missingArgs.front(), - "\" argument not given value.")); - return false; + if (parseResult.MaybeReportError(status.GetMakefile())) { + return true; } if (file.empty()) { status.SetError("RPATH_CHECK not given FILE option."); return false; } - if (rpath.empty() && - std::find(parsedArgs.begin(), parsedArgs.end(), "RPATH") == - parsedArgs.end()) { + if (!rpath) { status.SetError("RPATH_CHECK not given RPATH option."); return false; } @@ -1174,7 +1153,7 @@ bool HandleRPathCheckCommand(std::vector<std::string> const& args, // delete it. This is used during installation to re-install a file // if its RPath will change. if (cmSystemTools::FileExists(file, true) && - !cmSystemTools::CheckRPath(file, rpath)) { + !cmSystemTools::CheckRPath(file, *rpath)) { cmSystemTools::RemoveFile(file); } @@ -1203,7 +1182,8 @@ bool HandleReadElfCommand(std::vector<std::string> const& args, .Bind("RPATH"_s, &Arguments::RPath) .Bind("RUNPATH"_s, &Arguments::RunPath) .Bind("CAPTURE_ERROR"_s, &Arguments::Error); - Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2)); + Arguments const arguments = parser.Parse(cmMakeRange(args).advance(2), + /*unparsedArguments=*/nullptr); if (!cmSystemTools::FileExists(fileNameArg, true)) { status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg, @@ -1256,9 +1236,9 @@ bool HandleRealPathCommand(std::vector<std::string> const& args, return false; } - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { - std::string BaseDirectory; + cm::optional<std::string> BaseDirectory; bool ExpandTilde = false; }; static auto const parser = @@ -1267,22 +1247,18 @@ bool HandleRealPathCommand(std::vector<std::string> const& args, .Bind("EXPAND_TILDE"_s, &Arguments::ExpandTilde); std::vector<std::string> unparsedArguments; - std::vector<std::string> keywordsMissingValue; - std::vector<std::string> parsedKeywords; auto arguments = - parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments, - &keywordsMissingValue, &parsedKeywords); + parser.Parse(cmMakeRange(args).advance(3), &unparsedArguments); if (!unparsedArguments.empty()) { status.SetError("REAL_PATH called with unexpected arguments"); return false; } - if (!keywordsMissingValue.empty()) { - status.SetError("BASE_DIRECTORY requires a value"); - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } - if (parsedKeywords.empty()) { + if (!arguments.BaseDirectory) { arguments.BaseDirectory = status.GetMakefile().GetCurrentSourceDirectory(); } @@ -1301,7 +1277,7 @@ bool HandleRealPathCommand(std::vector<std::string> const& args, } cmCMakePath path(input, cmCMakePath::auto_format); - path = path.Absolute(arguments.BaseDirectory).Normal(); + path = path.Absolute(*arguments.BaseDirectory).Normal(); auto realPath = cmSystemTools::GetRealPath(path.GenericString()); status.GetMakefile().AddDefinition(args[2], realPath); @@ -1944,7 +1920,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args, std::string msg; std::string actualHash = hash->HashFile(file); if (actualHash == expectedHash) { - msg = cmStrCat("returning early; file already exists with expected ", + msg = cmStrCat("skipping download as file already exists with expected ", hashMatchMSG, '"'); if (!statusVar.empty()) { status.GetMakefile().AddDefinition(statusVar, cmStrCat(0, ";\"", msg)); @@ -2501,17 +2477,18 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, return false; } - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { - std::string Output; - std::string Input; - std::string Content; - std::string Condition; - std::string Target; - std::string NewLineStyle; + cm::optional<std::string> Output; + cm::optional<std::string> Input; + cm::optional<std::string> Content; + cm::optional<std::string> Condition; + cm::optional<std::string> Target; + cm::optional<std::string> NewLineStyle; bool NoSourcePermissions = false; bool UseSourcePermissions = false; - std::vector<std::string> FilePermissions; + ArgumentParser::NonEmpty<std::vector<std::string>> FilePermissions; + std::vector<cm::string_view> ParsedKeywords; }; static auto const parser = @@ -2524,18 +2501,15 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, .Bind("NO_SOURCE_PERMISSIONS"_s, &Arguments::NoSourcePermissions) .Bind("USE_SOURCE_PERMISSIONS"_s, &Arguments::UseSourcePermissions) .Bind("FILE_PERMISSIONS"_s, &Arguments::FilePermissions) - .Bind("NEWLINE_STYLE"_s, &Arguments::NewLineStyle); + .Bind("NEWLINE_STYLE"_s, &Arguments::NewLineStyle) + .BindParsedKeywords(&Arguments::ParsedKeywords); std::vector<std::string> unparsedArguments; - std::vector<std::string> keywordsMissingValues; - std::vector<std::string> parsedKeywords; Arguments const arguments = - parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments, - &keywordsMissingValues, &parsedKeywords); + parser.Parse(cmMakeRange(args).advance(1), &unparsedArguments); - if (!keywordsMissingValues.empty()) { - status.SetError("Incorrect arguments to GENERATE subcommand."); - return false; + if (arguments.MaybeReportError(status.GetMakefile())) { + return true; } if (!unparsedArguments.empty()) { @@ -2543,56 +2517,41 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, return false; } - bool mandatoryOptionsSpecified = false; - if (parsedKeywords.size() > 1) { - const bool outputOprionSpecified = parsedKeywords[0] == "OUTPUT"_s; - const bool inputOrContentSpecified = - parsedKeywords[1] == "INPUT"_s || parsedKeywords[1] == "CONTENT"_s; - if (outputOprionSpecified && inputOrContentSpecified) { - mandatoryOptionsSpecified = true; - } + if (!arguments.Output || arguments.ParsedKeywords[0] != "OUTPUT"_s) { + status.SetError("GENERATE requires OUTPUT as first option."); + return false; } - if (!mandatoryOptionsSpecified) { - status.SetError("Incorrect arguments to GENERATE subcommand."); + std::string const& output = *arguments.Output; + + if (!arguments.Input && !arguments.Content) { + status.SetError("GENERATE requires INPUT or CONTENT option."); return false; } + const bool inputIsContent = arguments.ParsedKeywords[1] == "CONTENT"_s; + if (!inputIsContent && arguments.ParsedKeywords[1] == "INPUT") { + status.SetError("Unknown argument to GENERATE subcommand."); + } + std::string const& input = + inputIsContent ? *arguments.Content : *arguments.Input; - const bool conditionOptionSpecified = - std::find(parsedKeywords.begin(), parsedKeywords.end(), "CONDITION"_s) != - parsedKeywords.end(); - if (conditionOptionSpecified && arguments.Condition.empty()) { + if (arguments.Condition && arguments.Condition->empty()) { status.SetError("CONDITION of sub-command GENERATE must not be empty " "if specified."); return false; } + std::string const& condition = + arguments.Condition ? *arguments.Condition : std::string(); - const bool targetOptionSpecified = - std::find(parsedKeywords.begin(), parsedKeywords.end(), "TARGET"_s) != - parsedKeywords.end(); - if (targetOptionSpecified && arguments.Target.empty()) { + if (arguments.Target && arguments.Target->empty()) { status.SetError("TARGET of sub-command GENERATE must not be empty " "if specified."); return false; } + std::string const& target = + arguments.Target ? *arguments.Target : std::string(); - const bool outputOptionSpecified = - std::find(parsedKeywords.begin(), parsedKeywords.end(), "OUTPUT"_s) != - parsedKeywords.end(); - if (outputOptionSpecified && parsedKeywords[0] != "OUTPUT"_s) { - status.SetError("Incorrect arguments to GENERATE subcommand."); - return false; - } - - const bool inputIsContent = parsedKeywords[1] != "INPUT"_s; - if (inputIsContent && parsedKeywords[1] != "CONTENT") { - status.SetError("Unknown argument to GENERATE subcommand."); - } - - const bool newLineStyleSpecified = - std::find(parsedKeywords.begin(), parsedKeywords.end(), - "NEWLINE_STYLE"_s) != parsedKeywords.end(); cmNewLineStyle newLineStyle; - if (newLineStyleSpecified) { + if (arguments.NewLineStyle) { std::string errorMessage; if (!newLineStyle.ReadFromArguments(args, errorMessage)) { status.SetError(cmStrCat("GENERATE ", errorMessage)); @@ -2600,11 +2559,6 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, } } - std::string input = arguments.Input; - if (inputIsContent) { - input = arguments.Content; - } - if (arguments.NoSourcePermissions && arguments.UseSourcePermissions) { status.SetError("given both NO_SOURCE_PERMISSIONS and " "USE_SOURCE_PERMISSIONS. Only one option allowed."); @@ -2662,8 +2616,7 @@ bool HandleGenerateCommand(std::vector<std::string> const& args, } } - AddEvaluationFile(input, arguments.Target, arguments.Output, - arguments.Condition, inputIsContent, + AddEvaluationFile(input, target, output, condition, inputIsContent, newLineStyle.GetCharacters(), permissions, status); return true; } @@ -2842,7 +2795,11 @@ bool HandleTimestampCommand(std::vector<std::string> const& args, unsigned int argsIndex = 1; - const std::string& filename = args[argsIndex++]; + std::string filename = args[argsIndex++]; + if (!cmsys::SystemTools::FileIsFullPath(filename)) { + filename = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', + filename); + } const std::string& outputVariable = args[argsIndex++]; @@ -3003,11 +2960,23 @@ bool HandleCreateLinkCommand(std::vector<std::string> const& args, // Check if the command requires a symbolic link. if (arguments.Symbolic) { - completed = static_cast<bool>( - cmSystemTools::CreateSymlink(fileName, newFileName, &result)); + cmsys::Status linked = + cmSystemTools::CreateSymlinkQuietly(fileName, newFileName); + if (linked) { + completed = true; + } else { + result = cmStrCat("failed to create symbolic link '", newFileName, + "': ", linked.GetString()); + } } else { - completed = static_cast<bool>( - cmSystemTools::CreateLink(fileName, newFileName, &result)); + cmsys::Status linked = + cmSystemTools::CreateLinkQuietly(fileName, newFileName); + if (linked) { + completed = true; + } else { + result = cmStrCat("failed to create link '", newFileName, + "': ", linked.GetString()); + } } // Check if copy-on-error is enabled in the arguments. @@ -3066,24 +3035,25 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, "\n ]])"); } - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { std::string ResolvedDependenciesVar; std::string UnresolvedDependenciesVar; std::string ConflictingDependenciesPrefix; std::string RPathPrefix; std::string BundleExecutable; - std::vector<std::string> Executables; - std::vector<std::string> Libraries; - std::vector<std::string> Directories; - std::vector<std::string> Modules; - std::vector<std::string> PreIncludeRegexes; - std::vector<std::string> PreExcludeRegexes; - std::vector<std::string> PostIncludeRegexes; - std::vector<std::string> PostExcludeRegexes; - std::vector<std::string> PostIncludeFiles; - std::vector<std::string> PostExcludeFiles; - std::vector<std::string> PostExcludeFilesStrict; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Executables; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Libraries; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Directories; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Modules; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PreIncludeRegexes; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PreExcludeRegexes; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeRegexes; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeRegexes; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeFiles; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeFiles; + ArgumentParser::MaybeEmpty<std::vector<std::string>> + PostExcludeFilesStrict; }; static auto const parser = @@ -3108,10 +3078,8 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, .Bind("POST_EXCLUDE_FILES_STRICT"_s, &Arguments::PostExcludeFilesStrict); std::vector<std::string> unrecognizedArguments; - std::vector<std::string> keywordsMissingValues; auto parsedArgs = - parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments, - &keywordsMissingValues); + parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments); auto argIt = unrecognizedArguments.begin(); if (argIt != unrecognizedArguments.end()) { status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); @@ -3119,26 +3087,9 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, return false; } - const std::vector<std::string> LIST_ARGS = { - "DIRECTORIES", - "EXECUTABLES", - "LIBRARIES", - "MODULES", - "POST_EXCLUDE_FILES", - "POST_EXCLUDE_FILES_STRICT", - "POST_EXCLUDE_REGEXES", - "POST_INCLUDE_FILES", - "POST_INCLUDE_REGEXES", - "PRE_EXCLUDE_REGEXES", - "PRE_INCLUDE_REGEXES", - }; - auto kwbegin = keywordsMissingValues.cbegin(); - auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS); - if (kwend != kwbegin) { - status.SetError(cmStrCat("Keywords missing values:\n ", - cmJoin(cmMakeRange(kwbegin, kwend), "\n "))); + if (parsedArgs.MaybeReportError(status.GetMakefile())) { cmSystemTools::SetFatalErrorOccurred(); - return false; + return true; } cmRuntimeDependencyArchive archive( @@ -3238,13 +3189,14 @@ bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args, bool HandleConfigureCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { - std::string Output; - std::string Content; + cm::optional<std::string> Output; + cm::optional<std::string> Content; bool EscapeQuotes = false; bool AtOnly = false; - std::string NewlineStyle; + // "NEWLINE_STYLE" requires one value, but we use a custom check below. + ArgumentParser::Maybe<std::string> NewlineStyle; }; static auto const parser = @@ -3256,11 +3208,8 @@ bool HandleConfigureCommand(std::vector<std::string> const& args, .Bind("NEWLINE_STYLE"_s, &Arguments::NewlineStyle); std::vector<std::string> unrecognizedArguments; - std::vector<std::string> keywordsMissingArguments; - std::vector<std::string> parsedKeywords; auto parsedArgs = - parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments, - &keywordsMissingArguments, &parsedKeywords); + parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments); auto argIt = unrecognizedArguments.begin(); if (argIt != unrecognizedArguments.end()) { @@ -3270,28 +3219,20 @@ bool HandleConfigureCommand(std::vector<std::string> const& args, return false; } - std::vector<std::string> mandatoryOptions{ "OUTPUT", "CONTENT" }; - for (auto const& e : mandatoryOptions) { - const bool optionHasNoValue = - std::find(keywordsMissingArguments.begin(), - keywordsMissingArguments.end(), - e) != keywordsMissingArguments.end(); - if (optionHasNoValue) { - status.SetError(cmStrCat("CONFIGURE ", e, " option needs a value.")); - cmSystemTools::SetFatalErrorOccurred(); - return false; - } + if (parsedArgs.MaybeReportError(status.GetMakefile())) { + cmSystemTools::SetFatalErrorOccurred(); + return true; } - for (auto const& e : mandatoryOptions) { - const bool optionGiven = - std::find(parsedKeywords.begin(), parsedKeywords.end(), e) != - parsedKeywords.end(); - if (!optionGiven) { - status.SetError(cmStrCat("CONFIGURE ", e, " option is mandatory.")); - cmSystemTools::SetFatalErrorOccurred(); - return false; - } + if (!parsedArgs.Output) { + status.SetError("CONFIGURE OUTPUT option is mandatory."); + cmSystemTools::SetFatalErrorOccurred(); + return false; + } + if (!parsedArgs.Content) { + status.SetError("CONFIGURE CONTENT option is mandatory."); + cmSystemTools::SetFatalErrorOccurred(); + return false; } std::string errorMessage; @@ -3303,7 +3244,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args, // Check for generator expressions std::string outputFile = cmSystemTools::CollapseFullPath( - parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory()); + *parsedArgs.Output, status.GetMakefile().GetCurrentBinaryDirectory()); std::string::size_type pos = outputFile.find_first_of("<>"); if (pos != std::string::npos) { @@ -3352,7 +3293,7 @@ bool HandleConfigureCommand(std::vector<std::string> const& args, fout.SetCopyIfDifferent(true); // copy input to output and expand variables from input at the same time - std::stringstream sin(parsedArgs.Content, std::ios::in); + std::stringstream sin(*parsedArgs.Content, std::ios::in); std::string inLine; std::string outLine; bool hasNewLine = false; @@ -3375,15 +3316,19 @@ bool HandleConfigureCommand(std::vector<std::string> const& args, bool HandleArchiveCreateCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { std::string Output; std::string Format; std::string Compression; std::string CompressionLevel; - std::string MTime; + // "MTIME" should require one value, but it has long been accidentally + // accepted without one and treated as if an empty value were given. + // Fixing this would require a policy. + ArgumentParser::Maybe<std::string> MTime; bool Verbose = false; - std::vector<std::string> Paths; + // "PATHS" requires at least one value, but use a custom check below. + ArgumentParser::MaybeEmpty<std::vector<std::string>> Paths; }; static auto const parser = @@ -3397,10 +3342,8 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args, .Bind("PATHS"_s, &Arguments::Paths); std::vector<std::string> unrecognizedArguments; - std::vector<std::string> keywordsMissingValues; auto parsedArgs = - parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments, - &keywordsMissingValues); + parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments); auto argIt = unrecognizedArguments.begin(); if (argIt != unrecognizedArguments.end()) { status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); @@ -3408,16 +3351,9 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args, return false; } - const std::vector<std::string> LIST_ARGS = { - "OUTPUT", "FORMAT", "COMPRESSION", "COMPRESSION_LEVEL", "MTIME", "PATHS" - }; - auto kwbegin = keywordsMissingValues.cbegin(); - auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS); - if (kwend != kwbegin) { - status.SetError(cmStrCat("Keywords missing values:\n ", - cmJoin(cmMakeRange(kwbegin, kwend), "\n "))); + if (parsedArgs.MaybeReportError(status.GetMakefile())) { cmSystemTools::SetFatalErrorOccurred(); - return false; + return true; } const char* knownFormats[] = { @@ -3506,13 +3442,13 @@ bool HandleArchiveCreateCommand(std::vector<std::string> const& args, bool HandleArchiveExtractCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { std::string Input; bool Verbose = false; bool ListOnly = false; std::string Destination; - std::vector<std::string> Patterns; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Patterns; bool Touch = false; }; @@ -3525,10 +3461,8 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args, .Bind("TOUCH"_s, &Arguments::Touch); std::vector<std::string> unrecognizedArguments; - std::vector<std::string> keywordsMissingValues; auto parsedArgs = - parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments, - &keywordsMissingValues); + parser.Parse(cmMakeRange(args).advance(1), &unrecognizedArguments); auto argIt = unrecognizedArguments.begin(); if (argIt != unrecognizedArguments.end()) { status.SetError(cmStrCat("Unrecognized argument: \"", *argIt, "\"")); @@ -3536,15 +3470,9 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args, return false; } - const std::vector<std::string> LIST_ARGS = { "INPUT", "DESTINATION", - "PATTERNS" }; - auto kwbegin = keywordsMissingValues.cbegin(); - auto kwend = cmRemoveMatching(keywordsMissingValues, LIST_ARGS); - if (kwend != kwbegin) { - status.SetError(cmStrCat("Keywords missing values:\n ", - cmJoin(cmMakeRange(kwbegin, kwend), "\n "))); + if (parsedArgs.MaybeReportError(status.GetMakefile())) { cmSystemTools::SetFatalErrorOccurred(); - return false; + return true; } std::string inFile = parsedArgs.Input; @@ -3599,10 +3527,15 @@ bool HandleArchiveExtractCommand(std::vector<std::string> const& args, return true; } -bool ValidateAndConvertPermissions(const std::vector<std::string>& permissions, - mode_t& perms, cmExecutionStatus& status) +bool ValidateAndConvertPermissions( + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> const& + permissions, + mode_t& perms, cmExecutionStatus& status) { - for (const auto& i : permissions) { + if (!permissions) { + return true; + } + for (const auto& i : *permissions) { if (!cmFSPermissions::stringToModeT(i, perms)) { status.SetError(i + " is an invalid permission specifier"); cmSystemTools::SetFatalErrorOccurred(); @@ -3634,11 +3567,14 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse, globber.SetRecurse(recurse); globber.SetRecurseListDirs(recurse); - struct Arguments + struct Arguments : public ArgumentParser::ParseResult { - std::vector<std::string> Permissions; - std::vector<std::string> FilePermissions; - std::vector<std::string> DirectoryPermissions; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> + Permissions; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> + FilePermissions; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> + DirectoryPermissions; }; static auto const parser = @@ -3648,21 +3584,20 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse, .Bind("DIRECTORY_PERMISSIONS"_s, &Arguments::DirectoryPermissions); std::vector<std::string> pathEntries; - std::vector<std::string> keywordsMissingValues; - Arguments parsedArgs = parser.Parse(cmMakeRange(args).advance(1), - &pathEntries, &keywordsMissingValues); + Arguments parsedArgs = + parser.Parse(cmMakeRange(args).advance(1), &pathEntries); // check validity of arguments - if (parsedArgs.Permissions.empty() && parsedArgs.FilePermissions.empty() && - parsedArgs.DirectoryPermissions.empty()) // no permissions given + if (!parsedArgs.Permissions && !parsedArgs.FilePermissions && + !parsedArgs.DirectoryPermissions) // no permissions given { status.SetError("No permissions given"); cmSystemTools::SetFatalErrorOccurred(); return false; } - if (!parsedArgs.Permissions.empty() && !parsedArgs.FilePermissions.empty() && - !parsedArgs.DirectoryPermissions.empty()) // all keywords are used + if (parsedArgs.Permissions && parsedArgs.FilePermissions && + parsedArgs.DirectoryPermissions) // all keywords are used { status.SetError("Remove either PERMISSIONS or FILE_PERMISSIONS or " "DIRECTORY_PERMISSIONS from the invocation"); @@ -3670,12 +3605,9 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse, return false; } - if (!keywordsMissingValues.empty()) { - for (const auto& i : keywordsMissingValues) { - status.SetError(i + " is not given any arguments"); - cmSystemTools::SetFatalErrorOccurred(); - } - return false; + if (parsedArgs.MaybeReportError(status.GetMakefile())) { + cmSystemTools::SetFatalErrorOccurred(); + return true; } // validate permissions @@ -3719,7 +3651,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse, if (cmSystemTools::FileExists(i, true)) { bool success = true; const mode_t& filePermissions = - parsedArgs.FilePermissions.empty() ? perms : fperms; + parsedArgs.FilePermissions ? fperms : perms; if (filePermissions) { success = SetPermissions(i, filePermissions, status); } @@ -3731,7 +3663,7 @@ bool HandleChmodCommandImpl(std::vector<std::string> const& args, bool recurse, else if (cmSystemTools::FileIsDirectory(i)) { bool success = true; const mode_t& directoryPermissions = - parsedArgs.DirectoryPermissions.empty() ? perms : dperms; + parsedArgs.DirectoryPermissions ? dperms : perms; if (directoryPermissions) { success = SetPermissions(i, directoryPermissions, status); } diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx index 1667807..ef55abf 100644 --- a/Source/cmFileCopier.cxx +++ b/Source/cmFileCopier.cxx @@ -15,7 +15,11 @@ #include "cmValue.h" #ifdef _WIN32 +# include <winerror.h> + # include "cmsys/FStream.hxx" +#else +# include <cerrno> #endif #include <cstring> @@ -504,11 +508,12 @@ bool cmFileCopier::InstallSymlinkChain(std::string& fromFile, cmSystemTools::RemoveFile(toFile); cmSystemTools::MakeDirectory(toFilePath); - if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) { - std::ostringstream e; - e << this->Name << " cannot create symlink \"" << toFile - << "\": " << cmSystemTools::GetLastSystemError() << "."; - this->Status.SetError(e.str()); + cmsys::Status status = + cmSystemTools::CreateSymlinkQuietly(symlinkTarget, toFile); + if (!status) { + std::string e = cmStrCat(this->Name, " cannot create symlink\n ", + toFile, "\nbecause: ", status.GetString()); + this->Status.SetError(e); return false; } } @@ -557,12 +562,24 @@ bool cmFileCopier::InstallSymlink(const std::string& fromFile, cmSystemTools::MakeDirectory(cmSystemTools::GetFilenamePath(toFile)); // Create the symlink. - if (!cmSystemTools::CreateSymlink(symlinkTarget, toFile)) { - std::ostringstream e; - e << this->Name << " cannot duplicate symlink \"" << fromFile - << "\" at \"" << toFile - << "\": " << cmSystemTools::GetLastSystemError() << "."; - this->Status.SetError(e.str()); + cmsys::Status status = + cmSystemTools::CreateSymlinkQuietly(symlinkTarget, toFile); + if (!status) { +#ifdef _WIN32 + bool const errorFileExists = status.GetWindows() == ERROR_FILE_EXISTS; +#else + bool const errorFileExists = status.GetPOSIX() == EEXIST; +#endif + std::string reason; + if (errorFileExists && cmSystemTools::FileIsDirectory(toFile)) { + reason = "A directory already exists at that location"; + } else { + reason = status.GetString(); + } + std::string e = + cmStrCat(this->Name, " cannot duplicate symlink\n ", fromFile, + "\nat\n ", toFile, "\nbecause: ", reason); + this->Status.SetError(e); return false; } } @@ -630,7 +647,10 @@ bool cmFileCopier::InstallDirectory(const std::string& source, { // Inform the user about this directory installation. this->ReportCopy(destination, TypeDir, - !cmSystemTools::FileIsDirectory(destination)); + !( // Report "Up-to-date:" for existing directories, + // but not symlinks to them. + cmSystemTools::FileIsDirectory(destination) && + !cmSystemTools::FileIsSymlink(destination))); // check if default dir creation permissions were set mode_t default_dir_mode_v = 0; diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx index 1da995a..b8d345f 100644 --- a/Source/cmFindBase.cxx +++ b/Source/cmFindBase.cxx @@ -2,15 +2,20 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmFindBase.h" +#include <algorithm> #include <cstddef> #include <deque> +#include <functional> #include <map> #include <utility> #include <cm/optional> #include <cmext/algorithm> +#include <cmext/string_view> #include "cmCMakePath.h" +#include "cmExecutionStatus.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -24,8 +29,6 @@ #include "cmWindowsRegistry.h" #include "cmake.h" -class cmExecutionStatus; - cmFindBase::cmFindBase(std::string findCommandName, cmExecutionStatus& status) : cmFindCommon(status) , FindCommandName(std::move(findCommandName)) @@ -138,6 +141,31 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) cmStrCat("given invalid value for \"REGISTRY_VIEW\": ", args[j])); return false; } + } else if (args[j] == "VALIDATOR") { + if (++j == args.size()) { + this->SetError("missing required argument for \"VALIDATOR\""); + return false; + } + auto command = this->Makefile->GetState()->GetCommand(args[j]); + if (command == nullptr) { + this->SetError(cmStrCat( + "command specified for \"VALIDATOR\" is undefined: ", args[j], '.')); + return false; + } + // ensure a macro is not specified as validator + const auto& validatorName = args[j]; + auto macros = cmExpandedList(this->Makefile->GetProperty("MACROS")); + if (std::find_if(macros.begin(), macros.end(), + [&validatorName](const std::string& item) { + return cmSystemTools::Strucmp(validatorName.c_str(), + item.c_str()) == 0; + }) != macros.end()) { + this->SetError(cmStrCat( + "command specified for \"VALIDATOR\" is not a function: ", args[j], + '.')); + return false; + } + this->ValidatorName = args[j]; } else if (this->CheckCommonArgument(args[j])) { doing = DoingNone; } else { @@ -188,6 +216,36 @@ bool cmFindBase::ParseArguments(std::vector<std::string> const& argsIn) return true; } +bool cmFindBase::Validate(const std::string& path) const +{ + if (this->ValidatorName.empty()) { + return true; + } + + // The validator command will be executed in an isolated scope. + cmMakefile::ScopePushPop varScope(this->Makefile); + cmMakefile::PolicyPushPop polScope(this->Makefile); + static_cast<void>(varScope); + static_cast<void>(polScope); + + auto resultName = + cmStrCat("CMAKE_"_s, cmSystemTools::UpperCase(this->FindCommandName), + "_VALIDATOR_STATUS"_s); + + this->Makefile->AddDefinitionBool(resultName, true); + + cmListFileFunction validator( + this->ValidatorName, 0, 0, + { cmListFileArgument(resultName, cmListFileArgument::Unquoted, 0), + cmListFileArgument(path, cmListFileArgument::Quoted, 0) }); + cmExecutionStatus status(*this->Makefile); + + if (this->Makefile->ExecuteCommand(validator, status)) { + return this->Makefile->GetDefinition(resultName).IsOn(); + } + return false; +} + void cmFindBase::ExpandPaths() { if (!this->NoDefaultPath) { diff --git a/Source/cmFindBase.h b/Source/cmFindBase.h index d197424..75d9a6d 100644 --- a/Source/cmFindBase.h +++ b/Source/cmFindBase.h @@ -31,6 +31,11 @@ public: */ virtual bool ParseArguments(std::vector<std::string> const& args); + /** + * To check validity of a found path using user's validator, if any + */ + bool Validate(const std::string& path) const; + protected: friend class cmFindBaseDebugState; void ExpandPaths(); @@ -63,6 +68,8 @@ protected: bool Required = false; + std::string ValidatorName; + private: // Add pieces of the search. void FillPackageRootPath(); diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 1c4039b..6296a60 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -192,6 +192,7 @@ struct cmFindLibraryHelper // Context information. cmMakefile* Makefile; + cmFindBase const* FindBase; cmGlobalGenerator* GG; // List of valid prefixes and suffixes. @@ -239,6 +240,11 @@ struct cmFindLibraryHelper bool CheckDirectory(std::string const& path); bool CheckDirectoryForName(std::string const& path, Name& name); + bool Validate(const std::string& path) const + { + return this->FindBase->Validate(path); + } + cmFindBaseDebugState DebugSearches; void DebugLibraryFailed(std::string const& name, std::string const& path) @@ -291,6 +297,7 @@ std::string const& get_suffixes(cmMakefile* mf) cmFindLibraryHelper::cmFindLibraryHelper(std::string debugName, cmMakefile* mf, cmFindBase const* base) : Makefile(mf) + , FindBase(base) , DebugMode(base->DebugModeEnabled()) , DebugSearches(std::move(debugName), base) { @@ -416,10 +423,13 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path, if (!exists) { this->DebugLibraryFailed(name.Raw, path); } else { - this->DebugLibraryFound(name.Raw, path); - this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath); - cmSystemTools::ConvertToUnixSlashes(this->BestPath); - return true; + auto testPath = cmSystemTools::CollapseFullPath(this->TestPath); + if (this->Validate(testPath)) { + this->DebugLibraryFound(name.Raw, path); + this->BestPath = testPath; + return true; + } + this->DebugLibraryFailed(name.Raw, path); } } @@ -443,8 +453,11 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path, this->TestPath = cmStrCat(path, origName); // Make sure the path is readable and is not a directory. if (cmSystemTools::FileExists(this->TestPath, true)) { - this->DebugLibraryFound(name.Raw, dir); + if (!this->Validate(cmSystemTools::CollapseFullPath(this->TestPath))) { + continue; + } + this->DebugLibraryFound(name.Raw, dir); // This is a matching file. Check if it is better than the // best name found so far. Earlier prefixes are preferred, // followed by earlier suffixes. For OpenBSD, shared library @@ -541,7 +554,10 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir() for (std::string const& n : this->Names) { fwPath = cmStrCat(d, n, ".framework"); if (cmSystemTools::FileIsDirectory(fwPath)) { - return cmSystemTools::CollapseFullPath(fwPath); + auto finalPath = cmSystemTools::CollapseFullPath(fwPath); + if (this->Validate(finalPath)) { + return finalPath; + } } } } @@ -558,7 +574,10 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName() for (std::string const& d : this->SearchPaths) { fwPath = cmStrCat(d, n, ".framework"); if (cmSystemTools::FileIsDirectory(fwPath)) { - return cmSystemTools::CollapseFullPath(fwPath); + auto finalPath = cmSystemTools::CollapseFullPath(fwPath); + if (this->Validate(finalPath)) { + return finalPath; + } } } } diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 8c6a0aa..3f8378b 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -5,7 +5,6 @@ #include <algorithm> #include <cassert> #include <cstdio> -#include <cstring> #include <deque> #include <functional> #include <iterator> @@ -43,8 +42,405 @@ # include <StorageDefs.h> #endif +#if defined(_WIN32) && !defined(__CYGWIN__) +# include <windows.h> +// http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx +# if !defined(KEY_WOW64_32KEY) +# define KEY_WOW64_32KEY 0x0200 +# endif +# if !defined(KEY_WOW64_64KEY) +# define KEY_WOW64_64KEY 0x0100 +# endif +#endif + class cmExecutionStatus; -class cmFileList; + +namespace { + +template <template <typename> class Op> +struct StrverscmpOp +{ + bool operator()(const std::string& lhs, const std::string& rhs) const + { + return Op<int>()(cmSystemTools::strverscmp(lhs, rhs), 0); + } +}; + +std::size_t collectPathsForDebug(std::string& buffer, + cmSearchPath const& searchPath, + std::size_t const startIndex = 0) +{ + const auto& paths = searchPath.GetPaths(); + if (paths.empty()) { + buffer += " none\n"; + return 0; + } + for (auto i = startIndex; i < paths.size(); i++) { + buffer += " " + paths[i].Path + "\n"; + } + return paths.size(); +} + +#if !(defined(_WIN32) && !defined(__CYGWIN__)) +class cmFindPackageCommandHoldFile +{ + const char* File; + +public: + cmFindPackageCommandHoldFile(const char* const f) + : File(f) + { + } + ~cmFindPackageCommandHoldFile() + { + if (this->File) { + cmSystemTools::RemoveFile(this->File); + } + } + cmFindPackageCommandHoldFile(const cmFindPackageCommandHoldFile&) = delete; + cmFindPackageCommandHoldFile& operator=( + const cmFindPackageCommandHoldFile&) = delete; + void Release() { this->File = nullptr; } +}; +#endif + +bool isDirentryToIgnore(const char* const fname) +{ + assert(fname != nullptr); + assert(fname[0] != 0); + return fname[0] == '.' && + (fname[1] == 0 || (fname[1] == '.' && fname[2] == 0)); +} + +class cmAppendPathSegmentGenerator +{ +public: + cmAppendPathSegmentGenerator(cm::string_view dirName) + : DirName{ dirName } + { + } + + std::string GetNextCandidate(const std::string& parent) + { + if (this->NeedReset) { + return {}; + } + this->NeedReset = true; + return cmStrCat(parent, '/', this->DirName); + } + + void Reset() { this->NeedReset = false; } + +private: + const cm::string_view DirName; + bool NeedReset = false; +}; + +class cmEnumPathSegmentsGenerator +{ +public: + cmEnumPathSegmentsGenerator(const std::vector<cm::string_view>& init) + : Names{ init } + , Current{ this->Names.get().cbegin() } + { + } + + std::string GetNextCandidate(const std::string& parent) + { + if (this->Current != this->Names.get().cend()) { + return cmStrCat(parent, '/', *this->Current++); + } + return {}; + } + + void Reset() { this->Current = this->Names.get().cbegin(); } + +private: + std::reference_wrapper<const std::vector<cm::string_view>> Names; + std::vector<cm::string_view>::const_iterator Current; +}; + +class cmCaseInsensitiveDirectoryListGenerator +{ +public: + cmCaseInsensitiveDirectoryListGenerator(cm::string_view name) + : DirectoryLister{} + , DirName{ name } + { + } + + std::string GetNextCandidate(const std::string& parent) + { + if (!this->Loaded) { + this->CurrentIdx = 0ul; + this->Loaded = true; + if (!this->DirectoryLister.Load(parent)) { + return {}; + } + } + + while (this->CurrentIdx < this->DirectoryLister.GetNumberOfFiles()) { + const char* const fname = + this->DirectoryLister.GetFile(this->CurrentIdx++); + if (isDirentryToIgnore(fname)) { + continue; + } + if (cmsysString_strcasecmp(fname, this->DirName.data()) == 0) { + auto candidate = cmStrCat(parent, '/', fname); + if (cmSystemTools::FileIsDirectory(candidate)) { + return candidate; + } + } + } + return {}; + } + + void Reset() { this->Loaded = false; } + +private: + cmsys::Directory DirectoryLister; + const cm::string_view DirName; + unsigned long CurrentIdx = 0ul; + bool Loaded = false; +}; + +class cmDirectoryListGenerator +{ +public: + cmDirectoryListGenerator(std::vector<std::string> const& names) + : Names{ names } + , Matches{} + , Current{ this->Matches.cbegin() } + { + } + virtual ~cmDirectoryListGenerator() = default; + + std::string GetNextCandidate(const std::string& parent) + { + // Construct a list of matches if not yet + if (this->Matches.empty()) { + cmsys::Directory directoryLister; + // ALERT `Directory::Load()` keeps only names + // internally and LOST entry type from `dirent`. + // So, `Directory::FileIsDirectory` gonna use + // `SystemTools::FileIsDirectory()` and waste a syscall. + // TODO Need to enhance the `Directory` class. + directoryLister.Load(parent); + + // ATTENTION Is it guaranteed that first two entries are + // `.` and `..`? + // TODO If so, just start with index 2 and drop the + // `isDirentryToIgnore(i)` condition to check. + for (auto i = 0ul; i < directoryLister.GetNumberOfFiles(); ++i) { + const char* const fname = directoryLister.GetFile(i); + if (isDirentryToIgnore(fname)) { + continue; + } + + for (const auto& n : this->Names.get()) { + // NOTE Customization point for `cmMacProjectDirectoryListGenerator` + const auto name = this->TransformNameBeforeCmp(n); + // Skip entries that don't match and non-directories. + // ATTENTION BTW, original code also didn't check if it's a symlink + // to a directory! + const auto equal = + (cmsysString_strncasecmp(fname, name.c_str(), name.length()) == 0); + if (equal && directoryLister.FileIsDirectory(i)) { + this->Matches.emplace_back(fname); + } + } + } + // NOTE Customization point for `cmProjectDirectoryListGenerator` + this->OnMatchesLoaded(); + + this->Current = this->Matches.cbegin(); + } + + if (this->Current != this->Matches.cend()) { + auto candidate = cmStrCat(parent, '/', *this->Current++); + return candidate; + } + + return {}; + } + + void Reset() + { + this->Matches.clear(); + this->Current = this->Matches.cbegin(); + } + +protected: + virtual void OnMatchesLoaded() {} + virtual std::string TransformNameBeforeCmp(std::string same) { return same; } + + std::reference_wrapper<const std::vector<std::string>> Names; + std::vector<std::string> Matches; + std::vector<std::string>::const_iterator Current; +}; + +class cmProjectDirectoryListGenerator : public cmDirectoryListGenerator +{ +public: + cmProjectDirectoryListGenerator(std::vector<std::string> const& names, + cmFindPackageCommand::SortOrderType so, + cmFindPackageCommand::SortDirectionType sd) + : cmDirectoryListGenerator{ names } + , SortOrder{ so } + , SortDirection{ sd } + { + } + +protected: + void OnMatchesLoaded() override + { + // check if there is a specific sorting order to perform + if (this->SortOrder != cmFindPackageCommand::None) { + cmFindPackageCommand::Sort(this->Matches.begin(), this->Matches.end(), + this->SortOrder, this->SortDirection); + } + } + +private: + // sort parameters + const cmFindPackageCommand::SortOrderType SortOrder; + const cmFindPackageCommand::SortDirectionType SortDirection; +}; + +class cmMacProjectDirectoryListGenerator : public cmDirectoryListGenerator +{ +public: + cmMacProjectDirectoryListGenerator(const std::vector<std::string>& names, + cm::string_view ext) + : cmDirectoryListGenerator{ names } + , Extension{ ext } + { + } + +protected: + std::string TransformNameBeforeCmp(std::string name) override + { + return cmStrCat(name, this->Extension); + } + +private: + const cm::string_view Extension; +}; + +class cmFileListGeneratorGlob +{ +public: + cmFileListGeneratorGlob(cm::string_view pattern) + : Pattern(pattern) + , Files{} + , Current{} + { + } + + std::string GetNextCandidate(const std::string& parent) + { + if (this->Files.empty()) { + // Glob the set of matching files. + std::string expr = cmStrCat(parent, this->Pattern); + cmsys::Glob g; + if (!g.FindFiles(expr)) { + return {}; + } + this->Files = g.GetFiles(); + this->Current = this->Files.cbegin(); + } + + // Skip non-directories + for (; this->Current != this->Files.cend() && + !cmSystemTools::FileIsDirectory(*this->Current); + ++this->Current) { + } + + return (this->Current != this->Files.cend()) ? *this->Current++ + : std::string{}; + } + + void Reset() + { + this->Files.clear(); + this->Current = this->Files.cbegin(); + } + +private: + cm::string_view Pattern; + std::vector<std::string> Files; + std::vector<std::string>::const_iterator Current; +}; + +#if defined(__LCC__) +# define CM_LCC_DIAG_SUPPRESS_1222 +# pragma diag_suppress 1222 // invalid error number (3288, but works anyway) +# define CM_LCC_DIAG_SUPPRESS_3288 +# pragma diag_suppress 3288 // parameter was declared but never referenced +#endif + +void ResetGenerator() +{ +} + +template <typename Generator> +void ResetGenerator(Generator&& generator) +{ + std::forward<Generator&&>(generator).Reset(); +} + +template <typename Generator, typename... Generators> +void ResetGenerator(Generator&& generator, Generators&&... generators) +{ + ResetGenerator(std::forward<Generator&&>(generator)); + ResetGenerator(std::forward<Generators&&>(generators)...); +} + +template <typename CallbackFn> +bool TryGeneratedPaths(CallbackFn&& filesCollector, + const std::string& fullPath) +{ + assert(!fullPath.empty() && fullPath.back() != '/'); + return std::forward<CallbackFn&&>(filesCollector)(fullPath + '/'); +} + +template <typename CallbackFn, typename Generator, typename... Rest> +bool TryGeneratedPaths(CallbackFn&& filesCollector, + const std::string& startPath, Generator&& gen, + Rest&&... tail) +{ + ResetGenerator(std::forward<Generator&&>(gen)); + for (auto path = gen.GetNextCandidate(startPath); !path.empty(); + path = gen.GetNextCandidate(startPath)) { + ResetGenerator(std::forward<Rest&&>(tail)...); + if (TryGeneratedPaths(std::forward<CallbackFn&&>(filesCollector), path, + std::forward<Rest&&>(tail)...)) { + return true; + } + } + return false; +} + +#ifdef CM_LCC_DIAG_SUPPRESS_3288 +# undef CM_LCC_DIAG_SUPPRESS_3288 +# pragma diag_default 3288 +#endif + +#ifdef CM_LCC_DIAG_SUPPRESS_1222 +# undef CM_LCC_DIAG_SUPPRESS_1222 +# pragma diag_default 1222 +#endif + +// Parse the version number and store the results that were +// successfully parsed. +int parseVersion(const std::string& version, unsigned int& major, + unsigned int& minor, unsigned int& patch, unsigned int& tweak) +{ + return std::sscanf(version.c_str(), "%u.%u.%u.%u", &major, &minor, &patch, + &tweak); +} + +} // anonymous namespace cmFindPackageCommand::PathLabel cmFindPackageCommand::PathLabel::PackageRedirect("PACKAGE_REDIRECT"); @@ -60,25 +456,10 @@ const cm::string_view cmFindPackageCommand::VERSION_ENDPOINT_INCLUDED( const cm::string_view cmFindPackageCommand::VERSION_ENDPOINT_EXCLUDED( "EXCLUDE"); -struct StrverscmpGreater -{ - bool operator()(const std::string& lhs, const std::string& rhs) const - { - return cmSystemTools::strverscmp(lhs, rhs) > 0; - } -}; - -struct StrverscmpLesser -{ - bool operator()(const std::string& lhs, const std::string& rhs) const - { - return cmSystemTools::strverscmp(lhs, rhs) < 0; - } -}; - void cmFindPackageCommand::Sort(std::vector<std::string>::iterator begin, std::vector<std::string>::iterator end, - SortOrderType order, SortDirectionType dir) + SortOrderType const order, + SortDirectionType const dir) { if (order == Name_order) { if (dir == Dec) { @@ -86,14 +467,13 @@ void cmFindPackageCommand::Sort(std::vector<std::string>::iterator begin, } else { std::sort(begin, end); } - } else if (order == Natural) - // natural order uses letters and numbers (contiguous numbers digit are - // compared such that e.g. 000 00 < 01 < 010 < 09 < 0 < 1 < 9 < 10 - { + } else if (order == Natural) { + // natural order uses letters and numbers (contiguous numbers digit are + // compared such that e.g. 000 00 < 01 < 010 < 09 < 0 < 1 < 9 < 10 if (dir == Dec) { - std::sort(begin, end, StrverscmpGreater()); + std::sort(begin, end, StrverscmpOp<std::greater>()); } else { - std::sort(begin, end, StrverscmpLesser()); + std::sort(begin, end, StrverscmpOp<std::less>()); } } // else do not sort @@ -113,11 +493,10 @@ cmFindPackageCommand::cmFindPackageCommand(cmExecutionStatus& status) void cmFindPackageCommand::AppendSearchPathGroups() { - std::vector<cmFindCommon::PathLabel>* labels; - // Update the All group with new paths. Note that package redirection must // take precedence over everything else, so it has to be first in the array. - labels = &this->PathGroupLabelMap[PathGroup::All]; + std::vector<cmFindCommon::PathLabel>* const labels = + &this->PathGroupLabelMap[PathGroup::All]; labels->insert(labels->begin(), PathLabel::PackageRedirect); labels->insert( std::find(labels->begin(), labels->end(), PathLabel::CMakeSystem), @@ -147,15 +526,15 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } // Lookup required version of CMake. - if (cmValue rv = + if (cmValue const rv = this->Makefile->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) { unsigned int v[3] = { 0, 0, 0 }; - sscanf(rv->c_str(), "%u.%u.%u", &v[0], &v[1], &v[2]); + std::sscanf(rv->c_str(), "%u.%u.%u", &v[0], &v[1], &v[2]); this->RequiredCMakeVersion = CMake_VERSION_ENCODE(v[0], v[1], v[2]); } // Lookup target architecture, if any. - if (cmValue arch = + if (cmValue const arch = this->Makefile->GetDefinition("CMAKE_LIBRARY_ARCHITECTURE")) { this->LibraryArchitecture = *arch; } @@ -184,7 +563,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // Check if User Package Registry should be disabled // The `CMAKE_FIND_USE_PACKAGE_REGISTRY` has // priority over the deprecated CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY - if (cmValue def = + if (cmValue const def = this->Makefile->GetDefinition("CMAKE_FIND_USE_PACKAGE_REGISTRY")) { this->NoUserRegistry = !cmIsOn(*def); } else if (this->Makefile->IsOn("CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY")) { @@ -194,7 +573,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // Check if System Package Registry should be disabled // The `CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY` has // priority over the deprecated CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY - if (cmValue def = this->Makefile->GetDefinition( + if (cmValue const def = this->Makefile->GetDefinition( "CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY")) { this->NoSystemRegistry = !cmIsOn(*def); } else if (this->Makefile->IsOn( @@ -208,7 +587,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } // Check if Sorting should be enabled - if (cmValue so = + if (cmValue const so = this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_ORDER")) { if (*so == "NAME") { @@ -219,7 +598,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->SortOrder = None; } } - if (cmValue sd = + if (cmValue const sd = this->Makefile->GetDefinition("CMAKE_FIND_PACKAGE_SORT_DIRECTION")) { this->SortDirection = (*sd == "ASC") ? Asc : Dec; } @@ -265,9 +644,9 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) cmsys::RegularExpression versionRegex( R"V(^([0-9]+(\.[0-9]+)*)(\.\.\.(<?)([0-9]+(\.[0-9]+)*))?$)V"); bool haveVersion = false; - std::set<unsigned int> configArgs; - std::set<unsigned int> moduleArgs; - for (unsigned int i = 1; i < args.size(); ++i) { + std::vector<std::size_t> configArgs; + std::vector<std::size_t> moduleArgs; + for (std::size_t i = 1u; i < args.size(); ++i) { if (args[i] == "QUIET") { this->Quiet = true; doing = DoingNone; @@ -281,17 +660,17 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->GlobalScope = true; doing = DoingNone; } else if (args[i] == "MODULE") { - moduleArgs.insert(i); + moduleArgs.push_back(i); doing = DoingNone; // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 // NOLINTNEXTLINE(bugprone-branch-clone) } else if (args[i] == "CONFIG") { - configArgs.insert(i); + configArgs.push_back(i); doing = DoingNone; // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 // NOLINTNEXTLINE(bugprone-branch-clone) } else if (args[i] == "NO_MODULE") { - configArgs.insert(i); + configArgs.push_back(i); doing = DoingNone; } else if (args[i] == "REQUIRED") { this->Required = true; @@ -301,36 +680,36 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } else if (args[i] == "OPTIONAL_COMPONENTS") { doing = DoingOptionalComponents; } else if (args[i] == "NAMES") { - configArgs.insert(i); + configArgs.push_back(i); doing = DoingNames; } else if (args[i] == "PATHS") { - configArgs.insert(i); + configArgs.push_back(i); doing = DoingPaths; } else if (args[i] == "HINTS") { - configArgs.insert(i); + configArgs.push_back(i); doing = DoingHints; } else if (args[i] == "PATH_SUFFIXES") { - configArgs.insert(i); + configArgs.push_back(i); doing = DoingPathSuffixes; } else if (args[i] == "CONFIGS") { - configArgs.insert(i); + configArgs.push_back(i); doing = DoingConfigs; } else if (args[i] == "NO_POLICY_SCOPE") { this->PolicyScope = false; doing = DoingNone; } else if (args[i] == "NO_CMAKE_PACKAGE_REGISTRY") { this->NoUserRegistry = true; - configArgs.insert(i); + configArgs.push_back(i); doing = DoingNone; } else if (args[i] == "NO_CMAKE_SYSTEM_PACKAGE_REGISTRY") { this->NoSystemRegistry = true; - configArgs.insert(i); + configArgs.push_back(i); doing = DoingNone; // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 // NOLINTNEXTLINE(bugprone-branch-clone) } else if (args[i] == "NO_CMAKE_BUILDS_PATH") { // Ignore legacy option. - configArgs.insert(i); + configArgs.push_back(i); doing = DoingNone; } else if (args[i] == "REGISTRY_VIEW") { if (++i == args.size()) { @@ -347,7 +726,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) return false; } } else if (this->CheckCommonArgument(args[i])) { - configArgs.insert(i); + configArgs.push_back(i); doing = DoingNone; } else if ((doing == DoingComponents) || (doing == DoingOptionalComponents)) { @@ -361,8 +740,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) requiredComponents.insert(args[i]); } - std::string req_var = this->Name + "_FIND_REQUIRED_" + args[i]; - componentVarDefs.emplace_back(req_var, isRequired); + componentVarDefs.emplace_back(this->Name + "_FIND_REQUIRED_" + args[i], + isRequired); // Append to the list of required components. components += components_sep; @@ -420,11 +799,11 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) if (!this->UseFindModules && !this->UseConfigFiles) { std::ostringstream e; e << "given options exclusive to Module mode:\n"; - for (unsigned int si : moduleArgs) { + for (auto si : moduleArgs) { e << " " << args[si] << "\n"; } e << "and options exclusive to Config mode:\n"; - for (unsigned int si : configArgs) { + for (auto si : configArgs) { e << " " << args[si] << "\n"; } e << "The options are incompatible."; @@ -443,20 +822,20 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) if (this->VersionComplete.empty() || components.empty()) { // Check whether we are recursing inside "Find<name>.cmake" within // another find_package(<name>) call. - std::string mod = cmStrCat(this->Name, "_FIND_MODULE"); + std::string const mod = cmStrCat(this->Name, "_FIND_MODULE"); if (this->Makefile->IsOn(mod)) { if (this->VersionComplete.empty()) { // Get version information from the outer call if necessary. // Requested version string. - std::string ver = cmStrCat(this->Name, "_FIND_VERSION_COMPLETE"); + std::string const ver = cmStrCat(this->Name, "_FIND_VERSION_COMPLETE"); this->VersionComplete = this->Makefile->GetSafeDefinition(ver); // Whether an exact version is required. - std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT"); + std::string const exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT"); this->VersionExact = this->Makefile->IsOn(exact); } if (components.empty()) { - std::string components_var = this->Name + "_FIND_COMPONENTS"; + std::string const components_var = this->Name + "_FIND_COMPONENTS"; components = this->Makefile->GetSafeDefinition(components_var); } } @@ -497,15 +876,6 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) return false; } - // Parse the version number and store the results that were - // successfully parsed. - auto parseVersion = [](const std::string& version, unsigned int& major, - unsigned int& minor, unsigned int& patch, - unsigned int& tweak) -> unsigned int { - return sscanf(version.c_str(), "%u.%u.%u.%u", &major, &minor, &patch, - &tweak); - }; - if (!this->Version.empty()) { this->VersionCount = parseVersion(this->Version, this->VersionMajor, this->VersionMinor, @@ -533,7 +903,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) } } - std::string disableFindPackageVar = + std::string const disableFindPackageVar = cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name); if (this->Makefile->IsOn(disableFindPackageVar)) { if (this->Required) { @@ -557,8 +927,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) // A dependency provider (if set) gets first look before other methods. // We do this before modifying the package root path stack because a // provider might use methods that ignore that. - cmState* state = this->Makefile->GetState(); - cmState::Command providerCommand = state->GetDependencyProviderCommand( + cmState* const state = this->Makefile->GetState(); + cmState::Command const providerCommand = state->GetDependencyProviderCommand( cmDependencyProvider::Method::FindPackage); if (bypassProvider) { if (this->DebugMode && providerCommand) { @@ -725,11 +1095,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) "package configuration file provided by " << this->Name << " (" << this->Name << "Config.cmake or " << cmSystemTools::LowerCase(this->Name) - << "-config.cmake). " - "Otherwise make Find" - << this->Name - << ".cmake available in " - "CMAKE_MODULE_PATH."; + << "-config.cmake). Otherwise make Find" << this->Name + << ".cmake available in CMAKE_MODULE_PATH."; } aw << "\n" "(Variable CMAKE_FIND_PACKAGE_WARN_NO_MODULE enabled this " @@ -813,22 +1180,22 @@ bool cmFindPackageCommand::FindPackageUsingConfigMode() void cmFindPackageCommand::SetVersionVariables( const std::function<void(const std::string&, cm::string_view)>& addDefinition, - const std::string& prefix, const std::string& version, unsigned int count, - unsigned int major, unsigned int minor, unsigned int patch, - unsigned int tweak) + const std::string& prefix, const std::string& version, + const unsigned int count, const unsigned int major, const unsigned int minor, + const unsigned int patch, const unsigned int tweak) { addDefinition(prefix, version); char buf[64]; snprintf(buf, sizeof(buf), "%u", major); addDefinition(prefix + "_MAJOR", buf); - sprintf(buf, "%u", minor); + snprintf(buf, sizeof(buf), "%u", minor); addDefinition(prefix + "_MINOR", buf); - sprintf(buf, "%u", patch); + snprintf(buf, sizeof(buf), "%u", patch); addDefinition(prefix + "_PATCH", buf); - sprintf(buf, "%u", tweak); + snprintf(buf, sizeof(buf), "%u", tweak); addDefinition(prefix + "_TWEAK", buf); - sprintf(buf, "%u", count); + snprintf(buf, sizeof(buf), "%u", count); addDefinition(prefix + "_COUNT", buf); } @@ -910,7 +1277,7 @@ void cmFindPackageCommand::SetModuleVariables( } void cmFindPackageCommand::AddFindDefinition(const std::string& var, - cm::string_view value) + const cm::string_view value) { if (cmValue old = this->Makefile->GetDefinition(var)) { this->OriginalDefs[var].exists = true; @@ -954,7 +1321,7 @@ bool cmFindPackageCommand::FindModule(bool& found) if (!mfile.empty()) { if (system) { - auto it = this->DeprecatedFindModules.find(this->Name); + auto const it = this->DeprecatedFindModules.find(this->Name); if (it != this->DeprecatedFindModules.end()) { cmPolicies::PolicyStatus status = this->Makefile->GetPolicyStatus(it->second); @@ -978,13 +1345,13 @@ bool cmFindPackageCommand::FindModule(bool& found) // Load the module we found, and set "<name>_FIND_MODULE" to true // while inside it. found = true; - std::string var = cmStrCat(this->Name, "_FIND_MODULE"); + std::string const var = cmStrCat(this->Name, "_FIND_MODULE"); this->Makefile->AddDefinition(var, "1"); bool result = this->ReadListFile(mfile, DoPolicyScope); this->Makefile->RemoveDefinition(var); if (this->DebugMode) { - std::string foundVar = cmStrCat(this->Name, "_FOUND"); + std::string const foundVar = cmStrCat(this->Name, "_FOUND"); if (this->Makefile->IsDefinitionSet(foundVar) && !this->Makefile->IsOn(foundVar)) { @@ -999,7 +1366,7 @@ bool cmFindPackageCommand::FindModule(bool& found) } bool cmFindPackageCommand::HandlePackageMode( - HandlePackageModeType handlePackageModeType) + const HandlePackageModeType handlePackageModeType) { this->ConsideredConfigs.clear(); @@ -1042,8 +1409,9 @@ bool cmFindPackageCommand::HandlePackageMode( } } - std::string foundVar = cmStrCat(this->Name, "_FOUND"); - std::string notFoundMessageVar = cmStrCat(this->Name, "_NOT_FOUND_MESSAGE"); + std::string const foundVar = cmStrCat(this->Name, "_FOUND"); + std::string const notFoundMessageVar = + cmStrCat(this->Name, "_NOT_FOUND_MESSAGE"); std::string notFoundMessage; // If the directory for the config file was found, try to read the file. @@ -1123,8 +1491,9 @@ bool cmFindPackageCommand::HandlePackageMode( << (this->VersionExact ? "exactly matches" : "is compatible with") << " requested version " << (this->VersionRange.empty() ? "" : "range ") << "\"" - << this->VersionComplete << "\".\n" - << "The following configuration files were considered but not " + << this->VersionComplete + << "\".\n" + "The following configuration files were considered but not " "accepted:\n"; for (ConfigFileInfo const& info : @@ -1172,8 +1541,9 @@ bool cmFindPackageCommand::HandlePackageMode( "package or SDK, be sure it has been installed."; } else // if(!this->UseFindModules && !this->UseConfigFiles) { - e << "No \"Find" << this->Name << ".cmake\" found in " - << "CMAKE_MODULE_PATH."; + e << "No \"Find" << this->Name + << ".cmake\" found in " + "CMAKE_MODULE_PATH."; aw << "Find" << this->Name @@ -1217,16 +1587,16 @@ bool cmFindPackageCommand::HandlePackageMode( this->Makefile->AddDefinition(foundVar, found ? "1" : "0"); // Set a variable naming the configuration file that was found. - std::string fileVar = cmStrCat(this->Name, "_CONFIG"); + std::string const fileVar = cmStrCat(this->Name, "_CONFIG"); if (found) { this->Makefile->AddDefinition(fileVar, this->FileFound); } else { this->Makefile->RemoveDefinition(fileVar); } - std::string consideredConfigsVar = + std::string const consideredConfigsVar = cmStrCat(this->Name, "_CONSIDERED_CONFIGS"); - std::string consideredVersionsVar = + std::string const consideredVersionsVar = cmStrCat(this->Name, "_CONSIDERED_VERSIONS"); std::string consideredConfigFiles; @@ -1312,7 +1682,7 @@ bool cmFindPackageCommand::FindConfig() void cmFindPackageCommand::SetConfigDirCacheVariable(const std::string& value) { - std::string help = + std::string const help = cmStrCat("The directory containing a CMake configuration file for ", this->Name, '.'); this->Makefile->AddCacheDefinition(this->Variable, value, help.c_str(), @@ -1351,7 +1721,7 @@ bool cmFindPackageCommand::FindAppBundleConfig() } bool cmFindPackageCommand::ReadListFile(const std::string& f, - PolicyScopeRule psr) + const PolicyScopeRule psr) { const bool noPolicyScope = !this->PolicyScope || psr == NoPolicyScope; @@ -1362,12 +1732,12 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f, if (this->Makefile->ReadDependentFile(f, noPolicyScope)) { return true; } - std::string e = cmStrCat("Error reading CMake code from \"", f, "\"."); + std::string const e = cmStrCat("Error reading CMake code from \"", f, "\"."); this->SetError(e); return false; } -void cmFindPackageCommand::AppendToFoundProperty(bool found) +void cmFindPackageCommand::AppendToFoundProperty(const bool found) { std::vector<std::string> foundContents; cmValue foundProp = @@ -1410,27 +1780,28 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found) void cmFindPackageCommand::AppendSuccessInformation() { { - std::string transitivePropName = + std::string const transitivePropName = cmStrCat("_CMAKE_", this->Name, "_TRANSITIVE_DEPENDENCY"); this->Makefile->GetState()->SetGlobalProperty(transitivePropName, "False"); } - std::string found = cmStrCat(this->Name, "_FOUND"); - std::string upperFound = cmSystemTools::UpperCase(found); + std::string const found = cmStrCat(this->Name, "_FOUND"); + std::string const upperFound = cmSystemTools::UpperCase(found); - bool upperResult = this->Makefile->IsOn(upperFound); - bool result = this->Makefile->IsOn(found); - bool packageFound = (result || upperResult); + bool const upperResult = this->Makefile->IsOn(upperFound); + bool const result = this->Makefile->IsOn(found); + bool const packageFound = (result || upperResult); this->AppendToFoundProperty(packageFound); // Record whether the find was quiet or not, so this can be used // e.g. in FeatureSummary.cmake - std::string quietInfoPropName = cmStrCat("_CMAKE_", this->Name, "_QUIET"); + std::string const quietInfoPropName = + cmStrCat("_CMAKE_", this->Name, "_QUIET"); this->Makefile->GetState()->SetGlobalProperty( quietInfoPropName, this->Quiet ? "TRUE" : "FALSE"); // set a global property to record the required version of this package - std::string versionInfoPropName = + std::string const versionInfoPropName = cmStrCat("_CMAKE_", this->Name, "_REQUIRED_VERSION"); std::string versionInfo; if (!this->VersionRange.empty()) { @@ -1442,28 +1813,13 @@ void cmFindPackageCommand::AppendSuccessInformation() this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName, versionInfo.c_str()); if (this->Required) { - std::string requiredInfoPropName = + std::string const requiredInfoPropName = cmStrCat("_CMAKE_", this->Name, "_TYPE"); this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName, "REQUIRED"); } } -inline std::size_t collectPathsForDebug(std::string& buffer, - cmSearchPath const& searchPath, - std::size_t startIndex = 0) -{ - const auto& paths = searchPath.GetPaths(); - if (paths.empty()) { - buffer += " none\n"; - return 0; - } - for (std::size_t i = startIndex; i < paths.size(); i++) { - buffer += " " + paths[i].Path + "\n"; - } - return paths.size(); -} - void cmFindPackageCommand::ComputePrefixes() { this->FillPrefixesPackageRedirect(); @@ -1674,14 +2030,6 @@ void cmFindPackageCommand::FillPrefixesSystemRegistry() } #if defined(_WIN32) && !defined(__CYGWIN__) -# include <windows.h> -// http://msdn.microsoft.com/en-us/library/aa384253%28v=vs.85%29.aspx -# if !defined(KEY_WOW64_32KEY) -# define KEY_WOW64_32KEY 0x0200 -# endif -# if !defined(KEY_WOW64_64KEY) -# define KEY_WOW64_64KEY 0x0100 -# endif void cmFindPackageCommand::LoadPackageRegistryWinUser() { // HKEY_CURRENT_USER\\Software shares 32-bit and 64-bit views. @@ -1704,7 +2052,8 @@ void cmFindPackageCommand::LoadPackageRegistryWinSystem() } } -void cmFindPackageCommand::LoadPackageRegistryWin(bool user, unsigned int view, +void cmFindPackageCommand::LoadPackageRegistryWin(const bool user, + const unsigned int view, cmSearchPath& outPaths) { std::wstring key = L"Software\\Kitware\\CMake\\Packages\\"; @@ -1756,28 +2105,8 @@ void cmFindPackageCommand::LoadPackageRegistryWin(bool user, unsigned int view, RegCloseKey(hKey); } } -#else -class cmFindPackageCommandHoldFile -{ - const char* File; - -public: - cmFindPackageCommandHoldFile(const char* f) - : File(f) - { - } - ~cmFindPackageCommandHoldFile() - { - if (this->File) { - cmSystemTools::RemoveFile(this->File); - } - } - cmFindPackageCommandHoldFile(const cmFindPackageCommandHoldFile&) = delete; - cmFindPackageCommandHoldFile& operator=( - const cmFindPackageCommandHoldFile&) = delete; - void Release() { this->File = nullptr; } -}; +#else void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir, cmSearchPath& outPaths) { @@ -1877,7 +2206,7 @@ void cmFindPackageCommand::FillPrefixesCMakeSystemVariable() std::vector<std::string> expanded = cmExpandedList(*prefix_paths); long count = 0; for (const auto& path : expanded) { - bool to_add = + bool const to_add = !(path == install_path_to_remove && ++count == install_prefix_count); if (to_add) { paths.AddPath(path); @@ -1941,7 +2270,7 @@ bool cmFindPackageCommand::SearchDirectory(std::string const& dir) std::string d = dir; if (!s.empty()) { d += s; - d += "/"; + d += '/'; } if (this->CheckDirectory(d)) { return true; @@ -1955,7 +2284,7 @@ bool cmFindPackageCommand::CheckDirectory(std::string const& dir) assert(!dir.empty() && dir.back() == '/'); // Look for the file in this directory. - std::string d = dir.substr(0, dir.size() - 1); + std::string const d = dir.substr(0, dir.size() - 1); if (this->FindConfigFile(d, this->FileFound)) { // Remove duplicate slashes. cmSystemTools::ConvertToUnixSlashes(this->FileFound); @@ -2028,8 +2357,8 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file, std::string& result_version) { // The version file will be loaded in an isolated scope. - cmMakefile::ScopePushPop varScope(this->Makefile); - cmMakefile::PolicyPushPop polScope(this->Makefile); + cmMakefile::ScopePushPop const varScope(this->Makefile); + cmMakefile::PolicyPushPop const polScope(this->Makefile); static_cast<void>(varScope); static_cast<void>(polScope); @@ -2076,7 +2405,7 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file, if (this->ReadListFile(version_file, NoPolicyScope)) { // Check the output variables. bool okay = this->Makefile->IsOn("PACKAGE_VERSION_EXACT"); - bool unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE"); + bool const unsuitable = this->Makefile->IsOn("PACKAGE_VERSION_UNSUITABLE"); if (!okay && !this->VersionExact) { okay = this->Makefile->IsOn("PACKAGE_VERSION_COMPATIBLE"); } @@ -2096,8 +2425,8 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file, unsigned int parsed_patch; unsigned int parsed_tweak; this->VersionFoundCount = - sscanf(this->VersionFound.c_str(), "%u.%u.%u.%u", &parsed_major, - &parsed_minor, &parsed_patch, &parsed_tweak); + parseVersion(this->VersionFound, parsed_major, parsed_minor, + parsed_patch, parsed_tweak); switch (this->VersionFoundCount) { case 4: this->VersionFoundTweak = parsed_tweak; @@ -2129,7 +2458,7 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file, void cmFindPackageCommand::StoreVersionFound() { // Store the whole version string. - std::string ver = cmStrCat(this->Name, "_VERSION"); + std::string const ver = cmStrCat(this->Name, "_VERSION"); auto addDefinition = [this](const std::string& variable, cm::string_view value) { this->Makefile->AddDefinition(variable, value); @@ -2145,357 +2474,6 @@ void cmFindPackageCommand::StoreVersionFound() } } -class cmFileListGeneratorBase -{ -public: - virtual ~cmFileListGeneratorBase() = default; - -protected: - bool Consider(std::string const& fullPath, cmFileList& listing); - -private: - bool Search(cmFileList&); - virtual bool Search(std::string const& parent, cmFileList&) = 0; - virtual std::unique_ptr<cmFileListGeneratorBase> Clone() const = 0; - friend class cmFileList; - cmFileListGeneratorBase* SetNext(cmFileListGeneratorBase const& next); - std::unique_ptr<cmFileListGeneratorBase> Next; -}; - -class cmFileList -{ -public: - virtual ~cmFileList() = default; - cmFileList& operator/(cmFileListGeneratorBase const& rhs) - { - if (this->Last) { - this->Last = this->Last->SetNext(rhs); - } else { - this->First = rhs.Clone(); - this->Last = this->First.get(); - } - return *this; - } - bool Search() - { - if (this->First) { - return this->First->Search(*this); - } - return false; - } - -private: - virtual bool Visit(std::string const& fullPath) = 0; - friend class cmFileListGeneratorBase; - std::unique_ptr<cmFileListGeneratorBase> First; - cmFileListGeneratorBase* Last = nullptr; -}; - -class cmFindPackageFileList : public cmFileList -{ -public: - cmFindPackageFileList(cmFindPackageCommand* fpc, bool use_suffixes = true) - : FPC(fpc) - , UseSuffixes(use_suffixes) - { - } - -private: - bool Visit(std::string const& fullPath) override - { - if (this->UseSuffixes) { - return this->FPC->SearchDirectory(fullPath); - } - return this->FPC->CheckDirectory(fullPath); - } - cmFindPackageCommand* FPC; - bool UseSuffixes; -}; - -bool cmFileListGeneratorBase::Search(cmFileList& listing) -{ - return this->Search("", listing); -} - -cmFileListGeneratorBase* cmFileListGeneratorBase::SetNext( - cmFileListGeneratorBase const& next) -{ - this->Next = next.Clone(); - return this->Next.get(); -} - -bool cmFileListGeneratorBase::Consider(std::string const& fullPath, - cmFileList& listing) -{ - if (!fullPath.empty() && !cmSystemTools::FileIsDirectory(fullPath)) { - return false; - } - if (this->Next) { - return this->Next->Search(fullPath + "/", listing); - } - return listing.Visit(fullPath + "/"); -} - -class cmFileListGeneratorFixed : public cmFileListGeneratorBase -{ -public: - cmFileListGeneratorFixed(std::string str) - : String(std::move(str)) - { - } - cmFileListGeneratorFixed(cmFileListGeneratorFixed const& r) - : String(r.String) - { - } - -private: - std::string String; - bool Search(std::string const& parent, cmFileList& lister) override - { - std::string fullPath = parent + this->String; - return this->Consider(fullPath, lister); - } - std::unique_ptr<cmFileListGeneratorBase> Clone() const override - { - std::unique_ptr<cmFileListGeneratorBase> g( - new cmFileListGeneratorFixed(*this)); - return g; - } -}; - -class cmFileListGeneratorEnumerate : public cmFileListGeneratorBase -{ -public: - cmFileListGeneratorEnumerate(std::vector<std::string> const& v) - : Vector(v) - { - } - cmFileListGeneratorEnumerate(cmFileListGeneratorEnumerate const& r) - : Vector(r.Vector) - { - } - -private: - std::vector<std::string> const& Vector; - bool Search(std::string const& parent, cmFileList& lister) override - { - for (std::string const& i : this->Vector) { - if (this->Consider(parent + i, lister)) { - return true; - } - } - return false; - } - std::unique_ptr<cmFileListGeneratorBase> Clone() const override - { - std::unique_ptr<cmFileListGeneratorBase> g( - new cmFileListGeneratorEnumerate(*this)); - return g; - } -}; - -class cmFileListGeneratorProject : public cmFileListGeneratorBase -{ -public: - cmFileListGeneratorProject(std::vector<std::string> const& names, - cmFindPackageCommand::SortOrderType so, - cmFindPackageCommand::SortDirectionType sd) - : Names(names) - { - this->SetSort(so, sd); - } - cmFileListGeneratorProject(cmFileListGeneratorProject const& r) - : Names(r.Names) - { - this->SetSort(r.SortOrder, r.SortDirection); - } - - void SetSort(cmFindPackageCommand::SortOrderType o, - cmFindPackageCommand::SortDirectionType d) - { - this->SortOrder = o; - this->SortDirection = d; - } - -protected: - // sort parameters - cmFindPackageCommand::SortOrderType SortOrder; - cmFindPackageCommand::SortDirectionType SortDirection; - -private: - std::vector<std::string> const& Names; - bool Search(std::string const& parent, cmFileList& lister) override - { - // Construct a list of matches. - std::vector<std::string> matches; - cmsys::Directory d; - d.Load(parent); - for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) { - const char* fname = d.GetFile(i); - if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) { - continue; - } - for (std::string const& n : this->Names) { - if (cmsysString_strncasecmp(fname, n.c_str(), n.length()) == 0) { - matches.emplace_back(fname); - } - } - } - - // before testing the matches check if there is a specific sorting order to - // perform - if (this->SortOrder != cmFindPackageCommand::None) { - cmFindPackageCommand::Sort(matches.begin(), matches.end(), - this->SortOrder, this->SortDirection); - } - - for (std::string const& i : matches) { - if (this->Consider(parent + i, lister)) { - return true; - } - } - return false; - } - std::unique_ptr<cmFileListGeneratorBase> Clone() const override - { - std::unique_ptr<cmFileListGeneratorBase> g( - new cmFileListGeneratorProject(*this)); - return g; - } -}; - -class cmFileListGeneratorMacProject : public cmFileListGeneratorBase -{ -public: - cmFileListGeneratorMacProject(std::vector<std::string> const& names, - const char* ext) - : Names(names) - , Extension(ext) - { - } - cmFileListGeneratorMacProject(cmFileListGeneratorMacProject const& r) - : Names(r.Names) - , Extension(r.Extension) - { - } - -private: - std::vector<std::string> const& Names; - std::string Extension; - bool Search(std::string const& parent, cmFileList& lister) override - { - // Construct a list of matches. - std::vector<std::string> matches; - cmsys::Directory d; - d.Load(parent); - for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) { - const char* fname = d.GetFile(i); - if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) { - continue; - } - for (std::string name : this->Names) { - name += this->Extension; - if (cmsysString_strcasecmp(fname, name.c_str()) == 0) { - matches.emplace_back(fname); - } - } - } - - for (std::string const& i : matches) { - if (this->Consider(parent + i, lister)) { - return true; - } - } - return false; - } - std::unique_ptr<cmFileListGeneratorBase> Clone() const override - { - std::unique_ptr<cmFileListGeneratorBase> g( - new cmFileListGeneratorMacProject(*this)); - return g; - } -}; - -class cmFileListGeneratorCaseInsensitive : public cmFileListGeneratorBase -{ -public: - cmFileListGeneratorCaseInsensitive(std::string str) - : String(std::move(str)) - { - } - cmFileListGeneratorCaseInsensitive( - cmFileListGeneratorCaseInsensitive const& r) - : String(r.String) - { - } - -private: - std::string String; - bool Search(std::string const& parent, cmFileList& lister) override - { - // Look for matching files. - std::vector<std::string> matches; - cmsys::Directory d; - d.Load(parent); - for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) { - const char* fname = d.GetFile(i); - if (strcmp(fname, ".") == 0 || strcmp(fname, "..") == 0) { - continue; - } - if (cmsysString_strcasecmp(fname, this->String.c_str()) == 0) { - if (this->Consider(parent + fname, lister)) { - return true; - } - } - } - return false; - } - std::unique_ptr<cmFileListGeneratorBase> Clone() const override - { - std::unique_ptr<cmFileListGeneratorBase> g( - new cmFileListGeneratorCaseInsensitive(*this)); - return g; - } -}; - -class cmFileListGeneratorGlob : public cmFileListGeneratorBase -{ -public: - cmFileListGeneratorGlob(std::string str) - : Pattern(std::move(str)) - { - } - cmFileListGeneratorGlob(cmFileListGeneratorGlob const& r) - : Pattern(r.Pattern) - { - } - -private: - std::string Pattern; - bool Search(std::string const& parent, cmFileList& lister) override - { - // Glob the set of matching files. - std::string expr = cmStrCat(parent, this->Pattern); - cmsys::Glob g; - if (!g.FindFiles(expr)) { - return false; - } - std::vector<std::string> const& files = g.GetFiles(); - - // Look for directories among the matches. - for (std::string const& f : files) { - if (this->Consider(f, lister)) { - return true; - } - } - return false; - } - std::unique_ptr<cmFileListGeneratorBase> Clone() const override - { - return cm::make_unique<cmFileListGeneratorGlob>(*this); - } -}; - bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) { assert(!prefix_in.empty() && prefix_in.back() == '/'); @@ -2515,148 +2493,101 @@ bool cmFindPackageCommand::SearchPrefix(std::string const& prefix_in) return false; } - // PREFIX/ (useful on windows or in build trees) + // PREFIX/ (useful on windows or in build trees) if (this->SearchDirectory(prefix_in)) { return true; } // Strip the trailing slash because the path generator is about to // add one. - std::string prefix = prefix_in.substr(0, prefix_in.size() - 1); + std::string const prefix = prefix_in.substr(0, prefix_in.size() - 1); - // PREFIX/(cmake|CMake)/ (useful on windows or in build trees) - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorCaseInsensitive("cmake"); - if (lister.Search()) { - return true; - } + auto searchFn = [this](const std::string& fullPath) -> bool { + return this->SearchDirectory(fullPath); + }; + + auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s }; + auto firstPkgDirGen = + cmProjectDirectoryListGenerator{ this->Names, this->SortOrder, + this->SortDirection }; + + // PREFIX/(cmake|CMake)/ (useful on windows or in build trees) + if (TryGeneratedPaths(searchFn, prefix, iCMakeGen)) { + return true; } - // PREFIX/(Foo|foo|FOO).*/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection); - if (lister.Search()) { - return true; - } + // PREFIX/(Foo|foo|FOO).*/ + if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen)) { + return true; } - // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection) / - cmFileListGeneratorCaseInsensitive("cmake"); - if (lister.Search()) { - return true; - } + // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/ + if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, iCMakeGen)) { + return true; + } + + auto secondPkgDirGen = + cmProjectDirectoryListGenerator{ this->Names, this->SortOrder, + this->SortDirection }; + + // PREFIX/(Foo|foo|FOO).*/(cmake|CMake)/(Foo|foo|FOO).*/ + if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, iCMakeGen, + secondPkgDirGen)) { + return true; } // Construct list of common install locations (lib and share). - std::vector<std::string> common; + std::vector<cm::string_view> common; + std::string libArch; if (!this->LibraryArchitecture.empty()) { - common.push_back("lib/" + this->LibraryArchitecture); + libArch = "lib/" + this->LibraryArchitecture; + common.emplace_back(libArch); } if (this->UseLib32Paths) { - common.emplace_back("lib32"); + common.emplace_back("lib32"_s); } if (this->UseLib64Paths) { - common.emplace_back("lib64"); + common.emplace_back("lib64"_s); } if (this->UseLibx32Paths) { - common.emplace_back("libx32"); + common.emplace_back("libx32"_s); } - common.emplace_back("lib"); - common.emplace_back("share"); + common.emplace_back("lib"_s); + common.emplace_back("share"_s); - // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorEnumerate(common) / - cmFileListGeneratorFixed("cmake") / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection); - if (lister.Search()) { - return true; - } + auto cmnGen = cmEnumPathSegmentsGenerator{ common }; + auto cmakeGen = cmAppendPathSegmentGenerator{ "cmake"_s }; + + // PREFIX/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/ + if (TryGeneratedPaths(searchFn, prefix, cmnGen, cmakeGen, firstPkgDirGen)) { + return true; } - // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorEnumerate(common) / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection); - if (lister.Search()) { - return true; - } + // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/ + if (TryGeneratedPaths(searchFn, prefix, cmnGen, firstPkgDirGen)) { + return true; } - // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorEnumerate(common) / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection) / - cmFileListGeneratorCaseInsensitive("cmake"); - if (lister.Search()) { - return true; - } + // PREFIX/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/ + if (TryGeneratedPaths(searchFn, prefix, cmnGen, firstPkgDirGen, iCMakeGen)) { + return true; } // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/cmake/(Foo|foo|FOO).*/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection) / - cmFileListGeneratorEnumerate(common) / - cmFileListGeneratorFixed("cmake") / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection); - if (lister.Search()) { - return true; - } + if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, cmnGen, cmakeGen, + secondPkgDirGen)) { + return true; } // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection) / - cmFileListGeneratorEnumerate(common) / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection); - if (lister.Search()) { - return true; - } + if (TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, cmnGen, + secondPkgDirGen)) { + return true; } // PREFIX/(Foo|foo|FOO).*/(lib/ARCH|lib*|share)/(Foo|foo|FOO).*/(cmake|CMake)/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection) / - cmFileListGeneratorEnumerate(common) / - cmFileListGeneratorProject(this->Names, this->SortOrder, - this->SortDirection) / - cmFileListGeneratorCaseInsensitive("cmake"); - if (lister.Search()) { - return true; - } - } - - return false; + return TryGeneratedPaths(searchFn, prefix, firstPkgDirGen, cmnGen, + secondPkgDirGen, iCMakeGen); } bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in) @@ -2665,56 +2596,36 @@ bool cmFindPackageCommand::SearchFrameworkPrefix(std::string const& prefix_in) // Strip the trailing slash because the path generator is about to // add one. - std::string prefix = prefix_in.substr(0, prefix_in.size() - 1); + std::string const prefix = prefix_in.substr(0, prefix_in.size() - 1); + + auto searchFn = [this](const std::string& fullPath) -> bool { + return this->SearchDirectory(fullPath); + }; + + auto iCMakeGen = cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s }; + auto fwGen = + cmMacProjectDirectoryListGenerator{ this->Names, ".framework"_s }; + auto rGen = cmAppendPathSegmentGenerator{ "Resources"_s }; + auto vGen = cmAppendPathSegmentGenerator{ "Versions"_s }; + auto grGen = cmFileListGeneratorGlob{ "/*/Resources"_s }; // <prefix>/Foo.framework/Resources/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorMacProject(this->Names, ".framework") / - cmFileListGeneratorFixed("Resources"); - if (lister.Search()) { - return true; - } + if (TryGeneratedPaths(searchFn, prefix, fwGen, rGen)) { + return true; } + // <prefix>/Foo.framework/Resources/CMake/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorMacProject(this->Names, ".framework") / - cmFileListGeneratorFixed("Resources") / - cmFileListGeneratorCaseInsensitive("cmake"); - if (lister.Search()) { - return true; - } + if (TryGeneratedPaths(searchFn, prefix, fwGen, rGen, iCMakeGen)) { + return true; } // <prefix>/Foo.framework/Versions/*/Resources/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorMacProject(this->Names, ".framework") / - cmFileListGeneratorFixed("Versions") / - cmFileListGeneratorGlob("*/Resources"); - if (lister.Search()) { - return true; - } + if (TryGeneratedPaths(searchFn, prefix, fwGen, vGen, grGen)) { + return true; } // <prefix>/Foo.framework/Versions/*/Resources/CMake/ - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorMacProject(this->Names, ".framework") / - cmFileListGeneratorFixed("Versions") / - cmFileListGeneratorGlob("*/Resources") / - cmFileListGeneratorCaseInsensitive("cmake"); - if (lister.Search()) { - return true; - } - } - - return false; + return TryGeneratedPaths(searchFn, prefix, fwGen, vGen, grGen, iCMakeGen); } bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in) @@ -2723,32 +2634,24 @@ bool cmFindPackageCommand::SearchAppBundlePrefix(std::string const& prefix_in) // Strip the trailing slash because the path generator is about to // add one. - std::string prefix = prefix_in.substr(0, prefix_in.size() - 1); + std::string const prefix = prefix_in.substr(0, prefix_in.size() - 1); + + auto searchFn = [this](const std::string& fullPath) -> bool { + return this->SearchDirectory(fullPath); + }; + + auto appGen = cmMacProjectDirectoryListGenerator{ this->Names, ".app"_s }; + auto crGen = cmAppendPathSegmentGenerator{ "Contents/Resources"_s }; // <prefix>/Foo.app/Contents/Resources - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorMacProject(this->Names, ".app") / - cmFileListGeneratorFixed("Contents/Resources"); - if (lister.Search()) { - return true; - } + if (TryGeneratedPaths(searchFn, prefix, appGen, crGen)) { + return true; } // <prefix>/Foo.app/Contents/Resources/CMake - { - cmFindPackageFileList lister(this); - lister / cmFileListGeneratorFixed(prefix) / - cmFileListGeneratorMacProject(this->Names, ".app") / - cmFileListGeneratorFixed("Contents/Resources") / - cmFileListGeneratorCaseInsensitive("cmake"); - if (lister.Search()) { - return true; - } - } - - return false; + return TryGeneratedPaths( + searchFn, prefix, appGen, crGen, + cmCaseInsensitiveDirectoryListGenerator{ "cmake"_s }); } // TODO: Debug cmsys::Glob double slash problem. diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 80fd8f8..28e00a1 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -153,8 +153,6 @@ private: bool SearchFrameworkPrefix(std::string const& prefix_in); bool SearchAppBundlePrefix(std::string const& prefix_in); - friend class cmFindPackageFileList; - struct OriginalDef { bool exists; diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx index 27074ff..74a69d8 100644 --- a/Source/cmFindPathCommand.cxx +++ b/Source/cmFindPathCommand.cxx @@ -88,7 +88,8 @@ std::string cmFindPathCommand::FindHeaderInFramework( if (!frameWorkName.empty()) { std::string fpath = cmStrCat(dir, frameWorkName, ".framework"); std::string intPath = cmStrCat(fpath, "/Headers/", fileName); - if (cmSystemTools::FileExists(intPath)) { + if (cmSystemTools::FileExists(intPath) && + this->Validate(this->IncludeFileInPath ? intPath : fpath)) { debug.FoundAt(intPath); if (this->IncludeFileInPath) { return intPath; @@ -124,7 +125,8 @@ std::string cmFindPathCommand::FindNormalHeader(cmFindBaseDebugState& debug) for (std::string const& n : this->Names) { for (std::string const& sp : this->SearchPaths) { tryPath = cmStrCat(sp, n); - if (cmSystemTools::FileExists(tryPath)) { + if (cmSystemTools::FileExists(tryPath) && + this->Validate(this->IncludeFileInPath ? tryPath : sp)) { debug.FoundAt(tryPath); if (this->IncludeFileInPath) { return tryPath; diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index a64e0e4..8a2a69e 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -27,6 +27,7 @@ struct cmFindProgramHelper cmFindBase const* base) : DebugSearches(std::move(debugName), base) , Makefile(makefile) + , FindBase(base) , PolicyCMP0109(makefile->GetPolicyStatus(cmPolicies::CMP0109)) { #if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) @@ -56,6 +57,7 @@ struct cmFindProgramHelper // Debug state cmFindBaseDebugState DebugSearches; cmMakefile* Makefile; + cmFindBase const* FindBase; cmPolicies::PolicyStatus PolicyCMP0109; @@ -94,7 +96,7 @@ struct cmFindProgramHelper this->TestNameExt = cmStrCat(name, ext); this->TestPath = cmSystemTools::CollapseFullPath( this->TestNameExt, path); - bool exists = this->FileIsExecutable(this->TestPath); + bool exists = this->FileIsValid(this->TestPath); exists ? this->DebugSearches.FoundAt(this->TestPath) : this->DebugSearches.FailedAt(this->TestPath); if (exists) { @@ -104,12 +106,12 @@ struct cmFindProgramHelper return false; }); } - bool FileIsExecutable(std::string const& file) const + bool FileIsValid(std::string const& file) const { -#ifdef _WIN32 if (!this->FileIsExecutableCMP0109(file)) { return false; } +#ifdef _WIN32 // Pretend the Windows "python" app installer alias does not exist. if (cmSystemTools::LowerCase(file).find("/windowsapps/python") != std::string::npos) { @@ -119,10 +121,8 @@ struct cmFindProgramHelper return false; } } - return true; -#else - return this->FileIsExecutableCMP0109(file); #endif + return this->FindBase->Validate(file); } bool FileIsExecutableCMP0109(std::string const& file) const { diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index b9400c9..3465c23 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -260,7 +260,7 @@ auto cmForEachFunctionBlocker::invoke( cmExecutionStatus status(mf); mf.ExecuteCommand(func, status); if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); + inStatus.SetReturnInvoked(status.GetReturnVariables()); result.Break = true; break; } diff --git a/Source/cmFunctionBlocker.cxx b/Source/cmFunctionBlocker.cxx index 40e692d..523482a 100644 --- a/Source/cmFunctionBlocker.cxx +++ b/Source/cmFunctionBlocker.cxx @@ -24,10 +24,11 @@ bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, auto self = mf.RemoveFunctionBlocker(); assert(self.get() == this); - if (!this->ArgumentsMatch(lff, mf)) { - cmListFileContext const& lfc = this->GetStartingContext(); - cmListFileContext closingContext = - cmListFileContext::FromListFileFunction(lff, lfc.FilePath); + cmListFileContext const& lfc = this->GetStartingContext(); + cmListFileContext closingContext = + cmListFileContext::FromListFileFunction(lff, lfc.FilePath); + if (this->EndCommandSupportsArguments() && + !this->ArgumentsMatch(lff, mf)) { std::ostringstream e; /* clang-format off */ e << "A logical block opening on the line\n" @@ -37,6 +38,15 @@ bool cmFunctionBlocker::IsFunctionBlocked(const cmListFileFunction& lff, << "with mis-matching arguments."; /* clang-format on */ mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); + } else if (!this->EndCommandSupportsArguments() && + !lff.Arguments().empty()) { + std::ostringstream e; + /* clang-format off */ + e << "A logical block closing on the line\n" + " " << closingContext << "\n" + "has unexpected arguments."; + /* clang-format on */ + mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str()); } return this->Replay(std::move(this->Functions), status); diff --git a/Source/cmFunctionBlocker.h b/Source/cmFunctionBlocker.h index 38abeba..3e096f2 100644 --- a/Source/cmFunctionBlocker.h +++ b/Source/cmFunctionBlocker.h @@ -38,6 +38,8 @@ private: virtual cm::string_view StartCommandName() const = 0; virtual cm::string_view EndCommandName() const = 0; + virtual bool EndCommandSupportsArguments() const { return true; } + virtual bool ArgumentsMatch(cmListFileFunction const& lff, cmMakefile& mf) const = 0; diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index 1359009..f4768b6 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -120,6 +120,7 @@ bool cmFunctionHelperCommand::operator()( return false; } if (status.GetReturnInvoked()) { + makefile.RaiseScope(status.GetReturnVariables()); break; } } diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index b529b8f..6212bbd 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -124,10 +124,10 @@ cmGeneratedFileStreamBase::~cmGeneratedFileStreamBase() void cmGeneratedFileStreamBase::Open(std::string const& name) { // Save the original name of the file. - this->Name = name; + this->Name = cmSystemTools::CollapseFullPath(name); // Create the name of the temporary file. - this->TempName = name; + this->TempName = this->Name; #if defined(__VMS) this->TempName += "_"; #else @@ -231,7 +231,7 @@ int cmGeneratedFileStreamBase::RenameFile(std::string const& oldname, void cmGeneratedFileStream::SetName(const std::string& fname) { - this->Name = fname; + this->Name = cmSystemTools::CollapseFullPath(fname); } void cmGeneratedFileStream::SetTempExt(std::string const& ext) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 6235a2a..6195d1f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -808,11 +808,16 @@ void handleSystemIncludesDep(cmLocalGenerator* lg, dagChecker, depTgt, language), result); } - if (!depTgt->IsImported() || excludeImported) { + if (!depTgt->GetPropertyAsBool("SYSTEM")) { return; } - if (depTgt->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) { - return; + if (depTgt->IsImported()) { + if (excludeImported) { + return; + } + if (depTgt->GetPropertyAsBool("IMPORTED_NO_SYSTEM")) { + return; + } } if (cmValue dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) { @@ -912,11 +917,19 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, return false; } - if (lang != "C" && lang != "CXX" && lang != "Fortran") { + if (lang != "C" && lang != "CXX" && lang != "CUDA" && lang != "Fortran") { // We do not define IPO behavior for other languages. return false; } + if (lang == "CUDA") { + // CUDA IPO requires both CUDA_ARCHITECTURES and CUDA_SEPARABLE_COMPILATION + if (cmIsOff(this->GetSafeProperty("CUDA_ARCHITECTURES")) || + cmIsOff(this->GetSafeProperty("CUDA_SEPARABLE_COMPILATION"))) { + return false; + } + } + cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069(); if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) { @@ -1708,7 +1721,8 @@ void addFileSetEntry(cmGeneratorTarget const* headTarget, } } if (!found) { - if (fileSet->GetType() == "HEADERS"_s) { + if (fileSet->GetType() == "HEADERS"_s || + fileSet->GetType() == "CXX_MODULE_HEADER_UNITS"_s) { headTarget->Makefile->GetOrCreateSourceGroup("Header Files") ->AddGroupFile(path); } @@ -1729,6 +1743,20 @@ void AddFileSetEntries(cmGeneratorTarget const* headTarget, addFileSetEntry(headTarget, config, dagChecker, headerSet, entries); } } + for (auto const& entry : headTarget->Target->GetCxxModuleSetsEntries()) { + for (auto const& name : cmExpandedList(entry.Value)) { + auto const* cxxModuleSet = headTarget->Target->GetFileSet(name); + addFileSetEntry(headTarget, config, dagChecker, cxxModuleSet, entries); + } + } + for (auto const& entry : + headTarget->Target->GetCxxModuleHeaderSetsEntries()) { + for (auto const& name : cmExpandedList(entry.Value)) { + auto const* cxxModuleHeaderSet = headTarget->Target->GetFileSet(name); + addFileSetEntry(headTarget, config, dagChecker, cxxModuleHeaderSet, + entries); + } + } } bool processSources(cmGeneratorTarget const* tgt, @@ -3409,7 +3437,9 @@ void cmGeneratorTarget::AddExplicitLanguageFlags(std::string& flags, "EXPLICIT_LANGUAGE"); } -void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const +void cmGeneratorTarget::AddCUDAArchitectureFlags(cmBuildStep compileOrLink, + const std::string& config, + std::string& flags) const { std::string property = this->GetSafeProperty("CUDA_ARCHITECTURES"); @@ -3441,6 +3471,7 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const std::string const& compiler = this->Makefile->GetSafeDefinition("CMAKE_CUDA_COMPILER_ID"); + const bool ipoEnabled = this->IsIPOEnabled("CUDA", config); // Check for special modes: `all`, `all-major`. if (property == "all" || property == "all-major") { @@ -3520,6 +3551,13 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const } if (compiler == "NVIDIA") { + if (ipoEnabled && compileOrLink == cmBuildStep::Link) { + if (cmValue cudaIPOFlags = + this->Makefile->GetDefinition("CMAKE_CUDA_LINK_OPTIONS_IPO")) { + flags += cudaIPOFlags; + } + } + for (CudaArchitecture& architecture : architectures) { flags += " --generate-code=arch=compute_" + architecture.name + ",code=["; @@ -3532,7 +3570,13 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const } } - if (architecture.real) { + if (ipoEnabled) { + if (compileOrLink == cmBuildStep::Compile) { + flags += "lto_" + architecture.name; + } else if (compileOrLink == cmBuildStep::Link) { + flags += "sm_" + architecture.name; + } + } else if (architecture.real) { flags += "sm_" + architecture.name; } @@ -5410,9 +5454,6 @@ std::string cmGeneratorTarget::GetObjectDirectory( std::string obj_dir = this->GlobalGenerator->ExpandCFGIntDir(this->ObjectDirectory, config); #if defined(__APPLE__) - // find and replace $(PROJECT_NAME) xcode placeholder - const std::string projectName = this->LocalGenerator->GetProjectName(); - cmSystemTools::ReplaceString(obj_dir, "$(PROJECT_NAME)", projectName); // Replace Xcode's placeholder for the object file directory since // installation and export scripts need to know the real directory. // Xcode has build-time settings (e.g. for sanitizers) that affect this, @@ -8719,8 +8760,85 @@ std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile( cmGeneratedFileStream fout(filename); fout.SetCopyIfDifferent(true); - fout << "#include <" << headerFilename << ">\n"; + // IWYU pragma: associated allows include what you use to + // consider the headerFile as part of the entire language + // unit within include-what-you-use and as a result allows + // one to get IWYU advice for headers :) + fout << "#include <" << headerFilename << "> // IWYU pragma: associated\n"; fout.close(); return filename; } + +bool cmGeneratorTarget::HaveCxx20ModuleSources() const +{ + auto const& fs_names = this->Target->GetAllFileSetNames(); + return std::any_of(fs_names.begin(), fs_names.end(), + [this](std::string const& name) -> bool { + auto const* file_set = this->Target->GetFileSet(name); + if (!file_set) { + this->Makefile->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("Target \"", this->Target->GetName(), + "\" is tracked to have file set \"", name, + "\", but it was not found.")); + return false; + } + + auto const& fs_type = file_set->GetType(); + return fs_type == "CXX_MODULES"_s || + fs_type == "CXX_MODULE_HEADER_UNITS"_s; + }); +} + +cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport( + std::string const& config) const +{ + auto const* state = this->Makefile->GetState(); + if (!state->GetLanguageEnabled("CXX")) { + return Cxx20SupportLevel::MissingCxx; + } + cmStandardLevelResolver standardResolver(this->Makefile); + if (!standardResolver.HaveStandardAvailable(this, "CXX", config, + "cxx_std_20")) { + return Cxx20SupportLevel::NoCxx20; + } + if (!this->Makefile->IsOn("CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP")) { + return Cxx20SupportLevel::MissingExperimentalFlag; + } + return Cxx20SupportLevel::Supported; +} + +void cmGeneratorTarget::CheckCxxModuleStatus(std::string const& config) const +{ + // Check for `CXX_MODULE*` file sets and a lack of support. + if (this->HaveCxx20ModuleSources()) { + switch (this->HaveCxxModuleSupport(config)) { + case cmGeneratorTarget::Cxx20SupportLevel::MissingCxx: + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The \"", this->GetName(), + "\" target has C++ module sources but the \"CXX\" language " + "has not been enabled")); + break; + case cmGeneratorTarget::Cxx20SupportLevel::MissingExperimentalFlag: + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The \"", this->GetName(), + "\" target has C++ module sources but its experimental " + "support has not been requested")); + break; + case cmGeneratorTarget::Cxx20SupportLevel::NoCxx20: + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "The \"", this->GetName(), + "\" target has C++ module sources but is not using at least " + "\"cxx_std_20\"")); + break; + case cmGeneratorTarget::Cxx20SupportLevel::Supported: + // All is well. + break; + } + } +} diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 6bce7d2..25e6a81 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -23,6 +23,7 @@ #include "cmStateTypes.h" #include "cmValue.h" +enum class cmBuildStep; class cmComputeLinkInformation; class cmCustomCommand; class cmGlobalGenerator; @@ -471,7 +472,9 @@ public: void AddExplicitLanguageFlags(std::string& flags, cmSourceFile const& sf) const; - void AddCUDAArchitectureFlags(std::string& flags) const; + void AddCUDAArchitectureFlags(cmBuildStep compileOrLink, + const std::string& config, + std::string& flags) const; void AddCUDAToolkitFlags(std::string& flags) const; void AddHIPArchitectureFlags(std::string& flags) const; @@ -1196,4 +1199,34 @@ public: bool operator()(cmGeneratorTarget const* t1, cmGeneratorTarget const* t2) const; }; + + // C++20 module support queries. + + /** + * Query whether the target expects C++20 module support. + * + * This will inspect the target itself to see if C++20 module + * support is expected to work based on its sources. + */ + bool HaveCxx20ModuleSources() const; + + enum class Cxx20SupportLevel + { + // C++ is not available. + MissingCxx, + // The experimental feature is not available. + MissingExperimentalFlag, + // The target does not require at least C++20. + NoCxx20, + // C++20 modules are available and working. + Supported, + }; + /** + * Query whether the target has C++20 module support available (regardless of + * whether it is required or not). + */ + Cxx20SupportLevel HaveCxxModuleSupport(std::string const& config) const; + + // Check C++ module status for the target. + void CheckCxxModuleStatus(std::string const& config) const; }; diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index bf019c3..138d3f1 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -183,8 +183,8 @@ void cmGhsMultiTargetGenerator::SetCompilerFlags(std::string const& config, auto i = this->FlagsByLanguage.find(language); if (i == this->FlagsByLanguage.end()) { std::string flags; - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, - language, config); + this->LocalGenerator->AddLanguageFlags( + flags, this->GeneratorTarget, cmBuildStep::Compile, language, config); this->LocalGenerator->AddCMP0018Flags(flags, this->GeneratorTarget, language, config); this->LocalGenerator->AddVisibilityPresetFlags( diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 0fe55f0..c2bf888 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -2554,9 +2554,9 @@ bool cmGlobalGenerator::NameResolvesToFramework( // This is where we change the path to point to the framework directory. // .tbd files also can be located in SDK frameworks (they are // placeholders for actual libraries shipped with the OS) -cm::optional<std::pair<std::string, std::string>> +cm::optional<cmGlobalGenerator::FrameworkDescriptor> cmGlobalGenerator::SplitFrameworkPath(const std::string& path, - bool extendedFormat) const + FrameworkFormat format) const { // Check for framework structure: // (/path/to/)?FwName.framework @@ -2571,20 +2571,29 @@ cmGlobalGenerator::SplitFrameworkPath(const std::string& path, auto name = frameworkPath.match(3); auto libname = cmSystemTools::GetFilenameWithoutExtension(frameworkPath.match(6)); + if (format == FrameworkFormat::Strict && libname.empty()) { + return cm::nullopt; + } if (!libname.empty() && !cmHasPrefix(libname, name)) { return cm::nullopt; } - return std::pair<std::string, std::string>{ frameworkPath.match(2), name }; + + if (libname.empty() || name.size() == libname.size()) { + return FrameworkDescriptor{ frameworkPath.match(2), name }; + } + + return FrameworkDescriptor{ frameworkPath.match(2), name, + libname.substr(name.size()) }; } - if (extendedFormat) { + if (format == FrameworkFormat::Extended) { // path format can be more flexible: (/path/to/)?fwName(.framework)? auto fwDir = cmSystemTools::GetParentDirectory(path); auto name = cmSystemTools::GetFilenameLastExtension(path) == ".framework" ? cmSystemTools::GetFilenameWithoutExtension(path) : cmSystemTools::GetFilenameName(path); - return std::pair<std::string, std::string>{ fwDir, name }; + return FrameworkDescriptor{ fwDir, name }; } return cm::nullopt; diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 6e3072b..89b2ea8 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -17,6 +17,7 @@ #include <cm/optional> #include <cmext/algorithm> +#include <cmext/string_view> #include "cm_codecvt.hxx" @@ -367,13 +368,61 @@ public: /** Determine if a name resolves to a framework on disk or a built target that is a framework. */ bool NameResolvesToFramework(const std::string& libname) const; - /** Split a framework path to the directory and name of the framework - * returns std::nullopt if the path does not match with framework format + /** Split a framework path to the directory and name of the framework as well + * as optiona; suffix. + * Returns std::nullopt if the path does not match with framework format * when extendedFormat is true, required format is relaxed (i.e. extension * `.framework' is optional). Used when FRAMEWORK link feature is * specified */ - cm::optional<std::pair<std::string, std::string>> SplitFrameworkPath( - const std::string& path, bool extendedFormat = false) const; + struct FrameworkDescriptor + { + FrameworkDescriptor(std::string directory, std::string name) + : Directory(std::move(directory)) + , Name(std::move(name)) + { + } + FrameworkDescriptor(std::string directory, std::string name, + std::string suffix) + : Directory(std::move(directory)) + , Name(std::move(name)) + , Suffix(std::move(suffix)) + { + } + std::string GetLinkName() const + { + return this->Suffix.empty() ? this->Name + : cmStrCat(this->Name, ',', this->Suffix); + } + std::string GetFullName() const + { + return cmStrCat(this->Name, ".framework/"_s, this->Name, this->Suffix); + } + std::string GetFrameworkPath() const + { + return this->Directory.empty() + ? cmStrCat(this->Name, ".framework"_s) + : cmStrCat(this->Directory, '/', this->Name, ".framework"_s); + } + std::string GetFullPath() const + { + return this->Directory.empty() + ? this->GetFullName() + : cmStrCat(this->Directory, '/', this->GetFullName()); + } + + const std::string Directory; + const std::string Name; + const std::string Suffix; + }; + enum class FrameworkFormat + { + Strict, + Relaxed, + Extended + }; + cm::optional<FrameworkDescriptor> SplitFrameworkPath( + const std::string& path, + FrameworkFormat format = FrameworkFormat::Relaxed) const; cmMakefile* FindMakefile(const std::string& start_dir) const; cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index acaed36..c326ca6 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -3,8 +3,10 @@ #include "cmGlobalNinjaGenerator.h" #include <algorithm> +#include <cassert> #include <cctype> #include <cstdio> +#include <functional> #include <sstream> #include <utility> @@ -14,6 +16,7 @@ #include <cm/string_view> #include <cmext/algorithm> #include <cmext/memory> +#include <cmext/string_view> #include <cm3p/json/reader.h> #include <cm3p/json/value.h> @@ -21,7 +24,9 @@ #include "cmsys/FStream.hxx" +#include "cmCxxModuleMapper.h" #include "cmDocumentationEntry.h" +#include "cmFileSet.h" #include "cmFortranParser.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpressionEvaluationFile.h" @@ -2480,13 +2485,53 @@ cm::optional<cmSourceInfo> cmcmd_cmake_ninja_depends_fortran( } } +struct CxxModuleFileSet +{ + std::string Name; + std::string RelativeDirectory; + std::string SourcePath; + std::string Type; + cmFileSetVisibility Visibility; + cm::optional<std::string> Destination; +}; + +struct CxxModuleBmiInstall +{ + std::string Component; + std::string Destination; + bool ExcludeFromAll; + bool Optional; + std::string Permissions; + std::string MessageLevel; + std::string ScriptLocation; +}; + +struct CxxModuleExport +{ + std::string Name; + std::string Destination; + std::string Prefix; + std::string CxxModuleInfoDir; + std::string Namespace; + bool Install; +}; + +struct cmGlobalNinjaGenerator::CxxModuleExportInfo +{ + std::map<std::string, CxxModuleFileSet> ObjectToFileSet; + cm::optional<CxxModuleBmiInstall> BmiInstallation; + std::vector<CxxModuleExport> Exports; + std::string Config; +}; + bool cmGlobalNinjaGenerator::WriteDyndepFile( std::string const& dir_top_src, std::string const& dir_top_bld, std::string const& dir_cur_src, std::string const& dir_cur_bld, std::string const& arg_dd, std::vector<std::string> const& arg_ddis, std::string const& module_dir, std::vector<std::string> const& linked_target_dirs, - std::string const& arg_lang, std::string const& arg_modmapfmt) + std::string const& arg_lang, std::string const& arg_modmapfmt, + CxxModuleExportInfo const& export_info) { // Setup path conversions. { @@ -2511,13 +2556,15 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( objects.push_back(std::move(info)); } + CxxModuleUsage usages; + // Map from module name to module file path, if known. std::map<std::string, std::string> mod_files; // Populate the module map with those provided by linked targets first. for (std::string const& linked_target_dir : linked_target_dirs) { std::string const ltmn = - cmStrCat(linked_target_dir, "/", arg_lang, "Modules.json"); + cmStrCat(linked_target_dir, '/', arg_lang, "Modules.json"); Json::Value ltm; cmsys::ifstream ltmf(ltmn.c_str(), std::ios::in | std::ios::binary); Json::Reader reader; @@ -2528,21 +2575,71 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( return false; } if (ltm.isObject()) { - for (Json::Value::iterator i = ltm.begin(); i != ltm.end(); ++i) { - mod_files[i.key().asString()] = i->asString(); + Json::Value const& target_modules = ltm["modules"]; + if (target_modules.isObject()) { + for (auto i = target_modules.begin(); i != target_modules.end(); ++i) { + mod_files[i.key().asString()] = i->asString(); + } + } + Json::Value const& target_modules_references = ltm["references"]; + if (target_modules_references.isObject()) { + for (auto i = target_modules_references.begin(); + i != target_modules_references.end(); ++i) { + if (i->isObject()) { + Json::Value const& reference_path = (*i)["path"]; + CxxModuleReference module_reference; + if (reference_path.isString()) { + module_reference.Path = reference_path.asString(); + } + Json::Value const& reference_method = (*i)["lookup-method"]; + if (reference_method.isString()) { + std::string reference = reference_method.asString(); + if (reference == "by-name") { + module_reference.Method = LookupMethod::ByName; + } else if (reference == "include-angle") { + module_reference.Method = LookupMethod::IncludeAngle; + } else if (reference == "include-quote") { + module_reference.Method = LookupMethod::IncludeQuote; + } + } + usages.Reference[i.key().asString()] = module_reference; + } + } + } + Json::Value const& target_modules_usage = ltm["usages"]; + if (target_modules_usage.isObject()) { + for (auto i = target_modules_usage.begin(); + i != target_modules_usage.end(); ++i) { + if (i->isArray()) { + for (auto j = i->begin(); j != i->end(); ++j) { + usages.Usage[i.key().asString()].insert(j->asString()); + } + } + } } } } - const char* module_ext = ""; - if (arg_modmapfmt == "gcc") { - module_ext = ".gcm"; + cm::optional<CxxModuleMapFormat> modmap_fmt; + if (arg_modmapfmt.empty()) { + // nothing to do. + } else if (arg_modmapfmt == "gcc") { + modmap_fmt = CxxModuleMapFormat::Gcc; + } else if (arg_modmapfmt == "msvc") { + modmap_fmt = CxxModuleMapFormat::Msvc; + } else { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep does not understand the ", arg_modmapfmt, + " module map format")); + return false; } + auto module_ext = CxxModuleMapExtension(modmap_fmt); + // Extend the module map with those provided by this target. // We do this after loading the modules provided by linked targets // in case we have one of the same name that must be preferred. - Json::Value tm = Json::objectValue; + Json::Value target_modules = Json::objectValue; for (cmScanDepInfo const& object : objects) { for (auto const& p : object.Provides) { std::string mod; @@ -2555,12 +2652,13 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( } } else { // Assume the module file path matches the logical module name. - std::string safe_logical_name = p.LogicalName; + std::string safe_logical_name = + p.LogicalName; // TODO: needs fixing for header units cmSystemTools::ReplaceString(safe_logical_name, ":", "-"); mod = cmStrCat(module_dir, safe_logical_name, module_ext); } mod_files[p.LogicalName] = mod; - tm[p.LogicalName] = mod; + target_modules[p.LogicalName] = mod; } } @@ -2568,6 +2666,32 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( ddf << "ninja_dyndep_version = 1.0\n"; { + CxxModuleLocations locs; + locs.RootDirectory = "."; + locs.PathForGenerator = [this](std::string const& path) -> std::string { + return this->ConvertToNinjaPath(path); + }; + locs.BmiLocationForModule = + [&mod_files](std::string const& logical) -> cm::optional<std::string> { + auto m = mod_files.find(logical); + if (m != mod_files.end()) { + return m->second; + } + return {}; + }; + + // Insert information about the current target's modules. + if (modmap_fmt) { + auto cycle_modules = CxxModuleUsageSeed(locs, objects, usages); + if (!cycle_modules.empty()) { + cmSystemTools::Error( + cmStrCat("Circular dependency detected in the C++ module import " + "graph. See modules named: \"", + cmJoin(cycle_modules, R"(", ")"_s), '"')); + return false; + } + } + cmNinjaBuild build("dyndep"); build.Outputs.emplace_back(""); for (cmScanDepInfo const& object : objects) { @@ -2589,60 +2713,332 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( build.Variables.emplace("restat", "1"); } - if (arg_modmapfmt.empty()) { - // nothing to do. - } else { - std::stringstream mm; - if (arg_modmapfmt == "gcc") { - // Documented in GCC's documentation. The format is a series of lines - // with a module name and the associated filename separated by - // spaces. The first line may use `$root` as the module name to - // specify a "repository root". That is used to anchor any relative - // paths present in the file (CMake should never generate any). - - // Write the root directory to use for module paths. - mm << "$root .\n"; - - for (auto const& l : object.Provides) { - auto m = mod_files.find(l.LogicalName); - if (m != mod_files.end()) { - mm << l.LogicalName << " " << this->ConvertToNinjaPath(m->second) - << "\n"; - } - } - for (auto const& r : object.Requires) { - auto m = mod_files.find(r.LogicalName); - if (m != mod_files.end()) { - mm << r.LogicalName << " " << this->ConvertToNinjaPath(m->second) - << "\n"; - } - } - } else { - cmSystemTools::Error( - cmStrCat("-E cmake_ninja_dyndep does not understand the ", - arg_modmapfmt, " module map format")); - return false; - } + if (modmap_fmt) { + auto mm = CxxModuleMapContent(*modmap_fmt, locs, object, usages); // XXX(modmap): If changing this path construction, change // `cmNinjaTargetGenerator::WriteObjectBuildStatements` to generate the // corresponding file path. cmGeneratedFileStream mmf(cmStrCat(object.PrimaryOutput, ".modmap")); - mmf << mm.str(); + mmf << mm; } this->WriteBuild(ddf, build); } } + Json::Value target_module_info = Json::objectValue; + target_module_info["modules"] = target_modules; + + auto& target_usages = target_module_info["usages"] = Json::objectValue; + for (auto const& u : usages.Usage) { + auto& mod_usage = target_usages[u.first] = Json::arrayValue; + for (auto const& v : u.second) { + mod_usage.append(v); + } + } + + auto name_for_method = [](LookupMethod method) -> cm::static_string_view { + switch (method) { + case LookupMethod::ByName: + return "by-name"_s; + case LookupMethod::IncludeAngle: + return "include-angle"_s; + case LookupMethod::IncludeQuote: + return "include-quote"_s; + } + assert(false && "unsupported lookup method"); + return ""_s; + }; + + auto& target_references = target_module_info["references"] = + Json::objectValue; + for (auto const& r : usages.Reference) { + auto& mod_ref = target_references[r.first] = Json::objectValue; + mod_ref["path"] = r.second.Path; + mod_ref["lookup-method"] = std::string(name_for_method(r.second.Method)); + } + // Store the map of modules provided by this target in a file for // use by dependents that reference this target in linked-target-dirs. std::string const target_mods_file = cmStrCat( cmSystemTools::GetFilenamePath(arg_dd), '/', arg_lang, "Modules.json"); cmGeneratedFileStream tmf(target_mods_file); - tmf << tm; + tmf << target_module_info; + + bool result = true; + + // Fortran doesn't support any of the file-set or BMI installation considered + // below. + if (arg_lang != "Fortran"_s) { + // Prepare the export information blocks. + std::string const config_upper = + cmSystemTools::UpperCase(export_info.Config); + std::vector<std::pair<std::unique_ptr<cmGeneratedFileStream>, + CxxModuleExport const*>> + exports; + for (auto const& exp : export_info.Exports) { + std::unique_ptr<cmGeneratedFileStream> properties; + + std::string const export_dir = + cmStrCat(exp.Prefix, '/', exp.CxxModuleInfoDir, '/'); + std::string const property_file_path = cmStrCat( + export_dir, "target-", exp.Name, '-', export_info.Config, ".cmake"); + properties = cm::make_unique<cmGeneratedFileStream>(property_file_path); + + // Set up the preamble. + *properties << "set_property(TARGET \"" << exp.Namespace << exp.Name + << "\"\n" + << " PROPERTY IMPORTED_CXX_MODULES_" << config_upper + << '\n'; + + exports.emplace_back(std::move(properties), &exp); + } + + std::unique_ptr<cmGeneratedFileStream> bmi_install_script; + if (export_info.BmiInstallation) { + bmi_install_script = cm::make_unique<cmGeneratedFileStream>( + export_info.BmiInstallation->ScriptLocation); + } + + auto cmEscape = [](cm::string_view str) { + return cmOutputConverter::EscapeForCMake( + str, cmOutputConverter::WrapQuotes::NoWrap); + }; + auto install_destination = + [&cmEscape](std::string const& dest) -> std::pair<bool, std::string> { + if (cmSystemTools::FileIsFullPath(dest)) { + return std::make_pair(true, cmEscape(dest)); + } + return std::make_pair(false, + cmStrCat("${_IMPORT_PREFIX}/", cmEscape(dest))); + }; - return true; + // public/private requirement tracking. + std::set<std::string> private_modules; + std::map<std::string, std::set<std::string>> public_source_requires; + + for (cmScanDepInfo const& object : objects) { + // Convert to forward slashes. + auto output_path = object.PrimaryOutput; +# ifdef _WIN32 + cmSystemTools::ConvertToUnixSlashes(output_path); +# endif + // Find the fileset for this object. + auto fileset_info_itr = export_info.ObjectToFileSet.find(output_path); + bool const has_provides = !object.Provides.empty(); + if (fileset_info_itr == export_info.ObjectToFileSet.end()) { + // If it provides anything, it should have a `CXX_MODULES` or + // `CXX_MODULE_INTERNAL_PARTITIONS` type and be present. + if (has_provides) { + // Take the first module provided to provide context. + auto const& provides = object.Provides[0]; + char const* ok_types = "`CXX_MODULES`"; + if (provides.LogicalName.find(':') != std::string::npos) { + ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if " + "it is not `export`ed)"; + } + cmSystemTools::Error( + cmStrCat("Output ", object.PrimaryOutput, " provides the `", + provides.LogicalName, + "` module but it is not found in a `FILE_SET` of type ", + ok_types)); + result = false; + } + + // This object file does not provide anything, so nothing more needs to + // be done. + continue; + } + + auto const& file_set = fileset_info_itr->second; + + // Verify the fileset type for the object. + if (file_set.Type == "CXX_MODULES"_s) { + if (!has_provides) { + cmSystemTools::Error(cmStrCat( + "Output ", object.PrimaryOutput, + " is of type `CXX_MODULES` but does not provide a module")); + result = false; + continue; + } + } else if (file_set.Type == "CXX_MODULE_INTERNAL_PARTITIONS"_s) { + if (!has_provides) { + cmSystemTools::Error(cmStrCat( + "Source ", file_set.SourcePath, + " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not " + "provide a module")); + result = false; + continue; + } + auto const& provides = object.Provides[0]; + if (provides.LogicalName.find(':') == std::string::npos) { + cmSystemTools::Error(cmStrCat( + "Source ", file_set.SourcePath, + " is of type `CXX_MODULE_INTERNAL_PARTITIONS` but does not " + "provide a module partition")); + result = false; + continue; + } + } else if (file_set.Type == "CXX_MODULE_HEADERS"_s) { + // TODO. + } else { + if (has_provides) { + auto const& provides = object.Provides[0]; + char const* ok_types = "`CXX_MODULES`"; + if (provides.LogicalName.find(':') != std::string::npos) { + ok_types = "`CXX_MODULES` (or `CXX_MODULE_INTERNAL_PARTITIONS` if " + "it is not `export`ed)"; + } + cmSystemTools::Error(cmStrCat( + "Source ", file_set.SourcePath, " provides the `", + provides.LogicalName, "` C++ module but is of type `", + file_set.Type, "` module but must be of type ", ok_types)); + result = false; + } + + // Not a C++ module; ignore. + continue; + } + + if (!cmFileSetVisibilityIsForInterface(file_set.Visibility)) { + // Nothing needs to be conveyed about non-`PUBLIC` modules. + for (auto const& p : object.Provides) { + private_modules.insert(p.LogicalName); + } + continue; + } + + // The module is public. Record what it directly requires. + { + auto& reqs = public_source_requires[file_set.SourcePath]; + for (auto const& r : object.Requires) { + reqs.insert(r.LogicalName); + } + } + + // Write out properties and install rules for any exports. + for (auto const& p : object.Provides) { + bool bmi_dest_is_abs = false; + std::string bmi_destination; + if (export_info.BmiInstallation) { + auto dest = + install_destination(export_info.BmiInstallation->Destination); + bmi_dest_is_abs = dest.first; + bmi_destination = cmStrCat(dest.second, '/'); + } + + std::string install_bmi_path; + std::string build_bmi_path; + auto m = mod_files.find(p.LogicalName); + if (m != mod_files.end()) { + install_bmi_path = + cmStrCat(bmi_destination, + cmEscape(cmSystemTools::GetFilenameName(m->second))); + build_bmi_path = cmEscape(m->second); + } + + for (auto const& exp : exports) { + std::string iface_source; + if (exp.second->Install && file_set.Destination) { + auto dest = install_destination(*file_set.Destination); + iface_source = cmStrCat( + dest.second, '/', cmEscape(file_set.RelativeDirectory), + cmEscape(cmSystemTools::GetFilenameName(file_set.SourcePath))); + } else { + iface_source = cmEscape(file_set.SourcePath); + } + + std::string bmi_path; + if (exp.second->Install && export_info.BmiInstallation) { + bmi_path = install_bmi_path; + } else if (!exp.second->Install) { + bmi_path = build_bmi_path; + } + + if (iface_source.empty()) { + // No destination for the C++ module source; ignore this property + // value. + continue; + } + + *exp.first << " \"" << cmEscape(p.LogicalName) << '=' + << iface_source; + if (!bmi_path.empty()) { + *exp.first << ',' << bmi_path; + } + *exp.first << "\"\n"; + } + + if (bmi_install_script) { + auto const& bmi_install = *export_info.BmiInstallation; + + *bmi_install_script << "if (CMAKE_INSTALL_COMPONENT STREQUAL \"" + << cmEscape(bmi_install.Component) << '\"'; + if (!bmi_install.ExcludeFromAll) { + *bmi_install_script << " OR NOT CMAKE_INSTALL_COMPONENT"; + } + *bmi_install_script << ")\n"; + *bmi_install_script << " file(INSTALL\n" + " DESTINATION \""; + if (!bmi_dest_is_abs) { + *bmi_install_script << "${CMAKE_INSTALL_PREFIX}/"; + } + *bmi_install_script << cmEscape(bmi_install.Destination) + << "\"\n" + " TYPE FILE\n"; + if (bmi_install.Optional) { + *bmi_install_script << " OPTIONAL\n"; + } + if (!bmi_install.MessageLevel.empty()) { + *bmi_install_script << " " << bmi_install.MessageLevel << "\n"; + } + if (!bmi_install.Permissions.empty()) { + *bmi_install_script << " PERMISSIONS" << bmi_install.Permissions + << "\n"; + } + *bmi_install_script << " FILES \"" << m->second << "\")\n"; + if (bmi_dest_is_abs) { + *bmi_install_script + << " list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n" + " \"" + << cmEscape(cmSystemTools::GetFilenameName(m->second)) + << "\")\n" + " if (CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n" + " message(WARNING\n" + " \"ABSOLUTE path INSTALL DESTINATION : " + "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n" + " endif ()\n" + " if (CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n" + " message(FATAL_ERROR\n" + " \"ABSOLUTE path INSTALL DESTINATION forbidden (by " + "caller): ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n" + " endif ()\n"; + } + *bmi_install_script << "endif ()\n"; + } + } + } + + // Add trailing parenthesis for the `set_property` call. + for (auto const& exp : exports) { + *exp.first << ")\n"; + } + + // Check that public sources only require public modules. + for (auto const& pub_reqs : public_source_requires) { + for (auto const& req : pub_reqs.second) { + if (private_modules.count(req)) { + cmSystemTools::Error(cmStrCat( + "Public C++ module source `", pub_reqs.first, "` requires the `", + req, "` C++ module which is provided by a private source")); + result = false; + } + } + } + } + + return result; } int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, @@ -2716,6 +3112,59 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, } } + cmGlobalNinjaGenerator::CxxModuleExportInfo export_info; + export_info.Config = tdi["config"].asString(); + if (export_info.Config.empty()) { + export_info.Config = "noconfig"; + } + Json::Value const& tdi_exports = tdi["exports"]; + if (tdi_exports.isArray()) { + for (auto const& tdi_export : tdi_exports) { + CxxModuleExport exp; + exp.Install = tdi_export["install"].asBool(); + exp.Name = tdi_export["export-name"].asString(); + exp.Destination = tdi_export["destination"].asString(); + exp.Prefix = tdi_export["export-prefix"].asString(); + exp.CxxModuleInfoDir = tdi_export["cxx-module-info-dir"].asString(); + exp.Namespace = tdi_export["namespace"].asString(); + + export_info.Exports.push_back(exp); + } + } + auto const& bmi_installation = tdi["bmi-installation"]; + if (bmi_installation.isObject()) { + CxxModuleBmiInstall bmi_install; + + bmi_install.Component = bmi_installation["component"].asString(); + bmi_install.Destination = bmi_installation["destination"].asString(); + bmi_install.ExcludeFromAll = bmi_installation["exclude-from-all"].asBool(); + bmi_install.Optional = bmi_installation["optional"].asBool(); + bmi_install.Permissions = bmi_installation["permissions"].asString(); + bmi_install.MessageLevel = bmi_installation["message-level"].asString(); + bmi_install.ScriptLocation = + bmi_installation["script-location"].asString(); + + export_info.BmiInstallation = bmi_install; + } + Json::Value const& tdi_cxx_modules = tdi["cxx-modules"]; + if (tdi_cxx_modules.isObject()) { + for (auto i = tdi_cxx_modules.begin(); i != tdi_cxx_modules.end(); ++i) { + CxxModuleFileSet& fsi = export_info.ObjectToFileSet[i.key().asString()]; + auto const& tdi_cxx_module_info = *i; + fsi.Name = tdi_cxx_module_info["name"].asString(); + fsi.RelativeDirectory = + tdi_cxx_module_info["relative-directory"].asString(); + fsi.SourcePath = tdi_cxx_module_info["source"].asString(); + fsi.Type = tdi_cxx_module_info["type"].asString(); + fsi.Visibility = cmFileSetVisibilityFromName( + tdi_cxx_module_info["visibility"].asString(), nullptr); + auto const& tdi_fs_dest = tdi_cxx_module_info["destination"]; + if (tdi_fs_dest.isString()) { + fsi.Destination = tdi_fs_dest.asString(); + } + } + } + cmake cm(cmake::RoleInternal, cmState::Unknown); cm.SetHomeDirectory(dir_top_src); cm.SetHomeOutputDirectory(dir_top_bld); @@ -2723,7 +3172,8 @@ int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg, if (!ggd || !cm::static_reference_cast<cmGlobalNinjaGenerator>(ggd).WriteDyndepFile( dir_top_src, dir_top_bld, dir_cur_src, dir_cur_bld, arg_dd, arg_ddis, - module_dir, linked_target_dirs, arg_lang, arg_modmapfmt)) { + module_dir, linked_target_dirs, arg_lang, arg_modmapfmt, + export_info)) { return 1; } return 0; diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index aa2df4d..dc4f444 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -417,13 +417,15 @@ public: bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); } void StripNinjaOutputPathPrefixAsSuffix(std::string& path); + struct CxxModuleExportInfo; bool WriteDyndepFile( std::string const& dir_top_src, std::string const& dir_top_bld, std::string const& dir_cur_src, std::string const& dir_cur_bld, std::string const& arg_dd, std::vector<std::string> const& arg_ddis, std::string const& module_dir, std::vector<std::string> const& linked_target_dirs, - std::string const& arg_lang, std::string const& arg_modmapfmt); + std::string const& arg_lang, std::string const& arg_modmapfmt, + CxxModuleExportInfo const& export_info); virtual std::string BuildAlias(const std::string& alias, const std::string& /*config*/) const diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 29eeb5a..bea2ae7 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -20,7 +20,6 @@ #include "cmDocumentationEntry.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" -#include "cmGlobalGeneratorFactory.h" #include "cmGlobalVisualStudio71Generator.h" #include "cmGlobalVisualStudio7Generator.h" #include "cmGlobalVisualStudioGenerator.h" @@ -38,7 +37,6 @@ #include "cmXMLWriter.h" #include "cmake.h" -static const char vs10generatorName[] = "Visual Studio 10 2010"; static std::map<std::string, std::vector<cmIDEFlagTable>> loadedFlagJsonFiles; static void ConvertToWindowsSlashes(std::string& s) @@ -51,137 +49,14 @@ static void ConvertToWindowsSlashes(std::string& s) } } -// Map generator name without year to name with year. -static const char* cmVS10GenName(const std::string& name, std::string& genName) -{ - if (strncmp(name.c_str(), vs10generatorName, - sizeof(vs10generatorName) - 6) != 0) { - return 0; - } - const char* p = name.c_str() + sizeof(vs10generatorName) - 6; - if (cmHasLiteralPrefix(p, " 2010")) { - p += 5; - } - genName = std::string(vs10generatorName) + p; - return p; -} - -class cmGlobalVisualStudio10Generator::Factory - : public cmGlobalGeneratorFactory -{ -public: - std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator( - const std::string& name, bool allowArch, cmake* cm) const override - { - std::string genName; - const char* p = cmVS10GenName(name, genName); - if (!p) { - return std::unique_ptr<cmGlobalGenerator>(); - } - if (!*p) { - return std::unique_ptr<cmGlobalGenerator>( - new cmGlobalVisualStudio10Generator(cm, genName, "")); - } - if (!allowArch || *p++ != ' ') { - return std::unique_ptr<cmGlobalGenerator>(); - } - if (strcmp(p, "Win64") == 0) { - return std::unique_ptr<cmGlobalGenerator>( - new cmGlobalVisualStudio10Generator(cm, genName, "x64")); - } - if (strcmp(p, "IA64") == 0) { - return std::unique_ptr<cmGlobalGenerator>( - new cmGlobalVisualStudio10Generator(cm, genName, "Itanium")); - } - return std::unique_ptr<cmGlobalGenerator>(); - } - - void GetDocumentation(cmDocumentationEntry& entry) const override - { - entry.Name = std::string(vs10generatorName) + " [arch]"; - entry.Brief = "Deprecated. Generates Visual Studio 2010 project files. " - "Optional [arch] can be \"Win64\" or \"IA64\"."; - } - - std::vector<std::string> GetGeneratorNames() const override - { - std::vector<std::string> names; - names.push_back(vs10generatorName); - return names; - } - - std::vector<std::string> GetGeneratorNamesWithPlatform() const override - { - std::vector<std::string> names; - names.push_back(vs10generatorName + std::string(" IA64")); - names.push_back(vs10generatorName + std::string(" Win64")); - return names; - } - - bool SupportsToolset() const override { return true; } - bool SupportsPlatform() const override { return true; } - - std::vector<std::string> GetKnownPlatforms() const override - { - std::vector<std::string> platforms; - platforms.emplace_back("x64"); - platforms.emplace_back("Win32"); - platforms.emplace_back("Itanium"); - return platforms; - } - - std::string GetDefaultPlatformName() const override { return "Win32"; } -}; - -std::unique_ptr<cmGlobalGeneratorFactory> -cmGlobalVisualStudio10Generator::NewFactory() -{ - return std::unique_ptr<cmGlobalGeneratorFactory>(new Factory); -} - cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( cmake* cm, const std::string& name, std::string const& platformInGeneratorName) : cmGlobalVisualStudio8Generator(cm, name, platformInGeneratorName) { - std::string vc10Express; - this->ExpressEdition = cmSystemTools::ReadRegistryValue( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\10.0\\Setup\\VC;" - "ProductDir", - vc10Express, cmSystemTools::KeyWOW64_32); - this->CudaEnabled = false; - { - std::string envPlatformToolset; - if (cmSystemTools::GetEnv("PlatformToolset", envPlatformToolset) && - envPlatformToolset == "Windows7.1SDK") { - // We are running from a Windows7.1SDK command prompt. - this->DefaultPlatformToolset = "Windows7.1SDK"; - } else { - this->DefaultPlatformToolset = "v100"; - } - } - this->DefaultCLFlagTableName = "v10"; - this->DefaultCSharpFlagTableName = "v10"; - this->DefaultLibFlagTableName = "v10"; - this->DefaultLinkFlagTableName = "v10"; this->DefaultCudaFlagTableName = "v10"; this->DefaultCudaHostFlagTableName = "v10"; - this->DefaultMasmFlagTableName = "v10"; this->DefaultNasmFlagTableName = "v10"; - this->DefaultRCFlagTableName = "v10"; - - this->Version = VSVersion::VS10; - this->PlatformToolsetNeedsDebugEnum = false; -} - -bool cmGlobalVisualStudio10Generator::MatchesGeneratorName( - const std::string& name) const -{ - std::string genName; - if (cmVS10GenName(name, genName)) { - return genName == this->GetName(); - } - return false; } bool cmGlobalVisualStudio10Generator::SetSystemName(std::string const& s, @@ -195,21 +70,6 @@ bool cmGlobalVisualStudio10Generator::SetSystemName(std::string const& s, return this->cmGlobalVisualStudio8Generator::SetSystemName(s, mf); } -bool cmGlobalVisualStudio10Generator::SetGeneratorPlatform( - std::string const& p, cmMakefile* mf) -{ - if (!this->cmGlobalVisualStudio8Generator::SetGeneratorPlatform(p, mf)) { - return false; - } - if (this->GetPlatformName() == "Itanium" || - this->GetPlatformName() == "x64") { - if (this->IsExpressEdition() && !this->Find64BitTools(mf)) { - return false; - } - } - return true; -} - static void cmCudaToolVersion(std::string& s) { // "CUDA x.y.props" => "x.y" @@ -389,6 +249,27 @@ bool cmGlobalVisualStudio10Generator::SetGeneratorToolset( this->GeneratorToolsetVersion.clear(); this->GeneratorToolsetVersionProps = {}; } break; + case AuxToolset::PropsIndeterminate: { + std::ostringstream e; + /* clang-format off */ + e << + "Generator\n" + " " << this->GetName() << "\n" + "given toolset and version specification\n" + " " << this->GetPlatformToolsetString() << ",version=" << + this->GeneratorToolsetVersion << "\n" + "has multiple matches installed at\n" << + " " << auxProps << "\n" << + "The toolset and version specification must resolve \n" << + "to a single installed toolset"; + ; + /* clang-format on */ + mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); + + // Clear the configured tool-set + this->GeneratorToolsetVersion.clear(); + this->GeneratorToolsetVersionProps = {}; + } break; } } @@ -1286,44 +1167,6 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand( return makeCommands; } -bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf) -{ - if (this->DefaultPlatformToolset == "v100") { - // The v100 64-bit toolset does not exist in the express edition. - this->DefaultPlatformToolset.clear(); - } - if (this->GetPlatformToolset()) { - return true; - } - // This edition does not come with 64-bit tools. Look for them. - // - // TODO: Detect available tools? x64\v100 exists but does not work? - // HKLM\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\4.0;VCTargetsPath - // c:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/Platforms/ - // {Itanium,Win32,x64}/PlatformToolsets/{v100,v90,Windows7.1SDK} - std::string winSDK_7_1; - if (cmSystemTools::ReadRegistryValue( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\" - "Windows\\v7.1;InstallationFolder", - winSDK_7_1)) { - std::ostringstream m; - m << "Found Windows SDK v7.1: " << winSDK_7_1; - mf->DisplayStatus(m.str(), -1); - this->DefaultPlatformToolset = "Windows7.1SDK"; - return true; - } else { - std::ostringstream e; - /* clang-format off */ - e << "Cannot enable 64-bit tools with Visual Studio 2010 Express.\n" - << "Install the Microsoft Windows SDK v7.1 to get 64-bit tools:\n" - << " http://msdn.microsoft.com/en-us/windows/bb980924.aspx"; - /* clang-format on */ - mf->IssueMessage(MessageType::FATAL_ERROR, e.str().c_str()); - cmSystemTools::SetFatalErrorOccurred(); - return false; - } -} - std::string cmGlobalVisualStudio10Generator::GenerateRuleFile( std::string const& output) const { @@ -1361,7 +1204,6 @@ const char* cmGlobalVisualStudio10Generator::GetToolsVersion() const { switch (this->Version) { case cmGlobalVisualStudioGenerator::VSVersion::VS9: - case cmGlobalVisualStudioGenerator::VSVersion::VS10: case cmGlobalVisualStudioGenerator::VSVersion::VS11: return "4.0"; diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 4977a84..b32c0a7 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -14,7 +14,6 @@ #include "cmGlobalVisualStudio8Generator.h" class cmGeneratorTarget; -class cmGlobalGeneratorFactory; class cmLocalGenerator; class cmMakefile; class cmSourceFile; @@ -29,14 +28,9 @@ struct cmIDEFlagTable; class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator { public: - static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory(); - bool IsVisualStudioAtLeast10() const override { return true; } - bool MatchesGeneratorName(const std::string& name) const override; - bool SetSystemName(std::string const& s, cmMakefile* mf) override; - bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override; bool SetGeneratorToolset(std::string const& ts, bool build, cmMakefile* mf) override; @@ -131,7 +125,6 @@ public: bool TargetsAndroid() const { return this->SystemIsAndroid; } const char* GetCMakeCFGIntDir() const override { return "$(Configuration)"; } - bool Find64BitTools(cmMakefile* mf); /** Generate an <output>.rule file path for a given command output. */ std::string GenerateRuleFile(std::string const& output) const override; @@ -200,7 +193,8 @@ protected: None, Default, PropsExist, - PropsMissing + PropsMissing, + PropsIndeterminate }; virtual AuxToolset FindAuxToolset(std::string& version, std::string& props) const; @@ -243,9 +237,6 @@ protected: bool MSBuildCommandInitialized = false; private: - class Factory; - friend class Factory; - struct LongestSourcePath { LongestSourcePath() @@ -269,7 +260,7 @@ private: std::string GeneratorToolsetVersion; - bool PlatformToolsetNeedsDebugEnum; + bool PlatformToolsetNeedsDebugEnum = false; bool ParseGeneratorToolset(std::string const& ts, cmMakefile* mf); @@ -290,7 +281,7 @@ private: std::string VCTargetsPath; bool FindVCTargetsPath(cmMakefile* mf); - bool CudaEnabled; + bool CudaEnabled = false; // We do not use the reload macros for VS >= 10. std::string GetUserMacrosDirectory() override { return ""; } diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index 10dc258..086d3af 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -77,7 +77,7 @@ public: void GetDocumentation(cmDocumentationEntry& entry) const override { entry.Name = std::string(vs11generatorName) + " [arch]"; - entry.Brief = "Generates Visual Studio 2012 project files. " + entry.Brief = "Deprecated. Generates Visual Studio 2012 project files. " "Optional [arch] can be \"Win64\" or \"ARM\"."; } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index f7f7317..ff76762 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -304,23 +304,23 @@ void cmGlobalVisualStudio7Generator::Generate() GetSLNFile(this->LocalGenerators[0].get())); } - if (this->Version == VSVersion::VS10 && + if (this->Version == VSVersion::VS11 && !this->CMakeInstance->GetIsInTryCompile()) { - std::string cmakeWarnVS10; + std::string cmakeWarnVS11; if (cmValue cached = this->CMakeInstance->GetState()->GetCacheEntryValue( - "CMAKE_WARN_VS10")) { - this->CMakeInstance->MarkCliAsUsed("CMAKE_WARN_VS10"); - cmakeWarnVS10 = *cached; + "CMAKE_WARN_VS11")) { + this->CMakeInstance->MarkCliAsUsed("CMAKE_WARN_VS11"); + cmakeWarnVS11 = *cached; } else { - cmSystemTools::GetEnv("CMAKE_WARN_VS10", cmakeWarnVS10); + cmSystemTools::GetEnv("CMAKE_WARN_VS11", cmakeWarnVS11); } - if (cmakeWarnVS10.empty() || !cmIsOff(cmakeWarnVS10)) { + if (cmakeWarnVS11.empty() || !cmIsOff(cmakeWarnVS11)) { this->CMakeInstance->IssueMessage( MessageType::WARNING, - "The \"Visual Studio 10 2010\" generator is deprecated " + "The \"Visual Studio 11 2012\" generator is deprecated " "and will be removed in a future version of CMake." "\n" - "Add CMAKE_WARN_VS10=OFF to the cache to disable this warning."); + "Add CMAKE_WARN_VS11=OFF to the cache to disable this warning."); } } } @@ -395,12 +395,27 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution( { VisualStudioFolders.clear(); + std::vector<std::string> configs = + root->GetMakefile()->GetGeneratorConfigs(cmMakefile::ExcludeEmptyConfig); + for (cmGeneratorTarget const* target : projectTargets) { if (!this->IsInSolution(target)) { continue; } bool written = false; + for (auto const& c : configs) { + target->CheckCxxModuleStatus(c); + } + + if (target->HaveCxx20ModuleSources() && !this->SupportsCxxModuleDyndep()) { + root->GetMakefile()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The \"", target->GetName(), + "\" target contains C++ module sources which are not " + "supported by the generator")); + } + // handle external vc project files cmValue expath = target->GetProperty("EXTERNAL_MSPROJECT"); if (expath) { diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index a55cf45..288069c 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -157,6 +157,8 @@ protected: cmValue typeGuid, const std::set<BT<std::pair<std::string, bool>>>& dependencies) = 0; + virtual bool SupportsCxxModuleDyndep() const { return false; } + std::string ConvertToSolutionPath(const std::string& path); std::set<std::string> IsPartOfDefaultBuild( diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index c6af20a..9d168d0 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -99,8 +99,6 @@ const char* cmGlobalVisualStudioGenerator::GetIDEVersion() const switch (this->Version) { case cmGlobalVisualStudioGenerator::VSVersion::VS9: return "9.0"; - case cmGlobalVisualStudioGenerator::VSVersion::VS10: - return "10.0"; case cmGlobalVisualStudioGenerator::VSVersion::VS11: return "11.0"; case cmGlobalVisualStudioGenerator::VSVersion::VS12: @@ -128,14 +126,6 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout) fout << "Microsoft Visual Studio Solution File, Format Version 10.00\n"; fout << "# Visual Studio 2008\n"; break; - case cmGlobalVisualStudioGenerator::VSVersion::VS10: - fout << "Microsoft Visual Studio Solution File, Format Version 11.00\n"; - if (this->ExpressEdition) { - fout << "# Visual C++ Express 2010\n"; - } else { - fout << "# Visual Studio 2010\n"; - } - break; case cmGlobalVisualStudioGenerator::VSVersion::VS11: fout << "Microsoft Visual Studio Solution File, Format Version 12.00\n"; if (this->ExpressEdition) { @@ -630,7 +620,8 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, RegCloseKey(hsubkey); } else { - std::cout << "error opening subkey: " << subkeyname << std::endl; + std::cout << "error opening subkey: " + << cmsys::Encoding::ToNarrow(subkeyname) << std::endl; std::cout << std::endl; } diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index f45b4d4..576e4f2 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -35,7 +35,6 @@ public: enum class VSVersion : uint16_t { VS9 = 90, - VS10 = 100, VS11 = 110, VS12 = 120, /* VS13 = 130 was skipped */ diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx index 7e36881..e9c8254 100644 --- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx +++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx @@ -127,8 +127,6 @@ static unsigned int VSVersionToMajor( switch (v) { case cmGlobalVisualStudioGenerator::VSVersion::VS9: return 9; - case cmGlobalVisualStudioGenerator::VSVersion::VS10: - return 10; case cmGlobalVisualStudioGenerator::VSVersion::VS11: return 11; case cmGlobalVisualStudioGenerator::VSVersion::VS12: @@ -151,8 +149,6 @@ static const char* VSVersionToToolset( switch (v) { case cmGlobalVisualStudioGenerator::VSVersion::VS9: return "v90"; - case cmGlobalVisualStudioGenerator::VSVersion::VS10: - return "v100"; case cmGlobalVisualStudioGenerator::VSVersion::VS11: return "v110"; case cmGlobalVisualStudioGenerator::VSVersion::VS12: @@ -175,8 +171,6 @@ static std::string VSVersionToMajorString( switch (v) { case cmGlobalVisualStudioGenerator::VSVersion::VS9: return "9"; - case cmGlobalVisualStudioGenerator::VSVersion::VS10: - return "10"; case cmGlobalVisualStudioGenerator::VSVersion::VS11: return "11"; case cmGlobalVisualStudioGenerator::VSVersion::VS12: @@ -198,7 +192,6 @@ static const char* VSVersionToAndroidToolset( { switch (v) { case cmGlobalVisualStudioGenerator::VSVersion::VS9: - case cmGlobalVisualStudioGenerator::VSVersion::VS10: case cmGlobalVisualStudioGenerator::VSVersion::VS11: case cmGlobalVisualStudioGenerator::VSVersion::VS12: return ""; @@ -500,7 +493,6 @@ bool cmGlobalVisualStudioVersionedGenerator::MatchesGeneratorName( std::string genName; switch (this->Version) { case cmGlobalVisualStudioGenerator::VSVersion::VS9: - case cmGlobalVisualStudioGenerator::VSVersion::VS10: case cmGlobalVisualStudioGenerator::VSVersion::VS11: case cmGlobalVisualStudioGenerator::VSVersion::VS12: case cmGlobalVisualStudioGenerator::VSVersion::VS14: @@ -743,7 +735,6 @@ cmGlobalVisualStudioVersionedGenerator::GetAndroidApplicationTypeRevision() { switch (this->Version) { case cmGlobalVisualStudioGenerator::VSVersion::VS9: - case cmGlobalVisualStudioGenerator::VSVersion::VS10: case cmGlobalVisualStudioGenerator::VSVersion::VS11: case cmGlobalVisualStudioGenerator::VSVersion::VS12: return ""; @@ -770,12 +761,15 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset( cmSystemTools::ConvertToUnixSlashes(instancePath); // Translate three-component format accepted by "vcvarsall -vcvars_ver=". - cmsys::RegularExpression threeComponent( + cmsys::RegularExpression threeComponentRegex( "^([0-9]+\\.[0-9]+)\\.[0-9][0-9][0-9][0-9][0-9]$"); - if (threeComponent.find(version)) { + // The two-component format represents the two major components of the + // three-component format + cmsys::RegularExpression twoComponentRegex("^([0-9]+\\.[0-9]+)$"); + if (threeComponentRegex.find(version)) { // Load "VC/Auxiliary/Build/*/Microsoft.VCToolsVersion.*.txt" files // with two matching components to check their three-component version. - std::string const& twoComponent = threeComponent.match(1); + std::string const& twoComponent = threeComponentRegex.match(1); std::string pattern = cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s, twoComponent, "*/Microsoft.VCToolsVersion."_s, twoComponent, "*.txt"_s); @@ -801,6 +795,34 @@ cmGlobalVisualStudioVersionedGenerator::FindAuxToolset( } } } + } else if (twoComponentRegex.find(version)) { + std::string const& twoComponent = twoComponentRegex.match(1); + std::string pattern = + cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s, twoComponent, + "*/Microsoft.VCToolsVersion."_s, twoComponent, "*.txt"_s); + cmsys::Glob glob; + glob.SetRecurseThroughSymlinks(false); + // Since we are only using the first two components of the toolset version, + // we require a definite match + if (glob.FindFiles(pattern) && glob.GetFiles().size() == 1) { + std::string const& txt = glob.GetFiles()[0]; + std::string ver; + cmsys::ifstream fin(txt.c_str()); + if (fin && std::getline(fin, ver)) { + // Strip trailing whitespace. + ver = ver.substr(0, ver.find_first_not_of("0123456789.")); + // We assume the version is correct, since it is the only one that + // matched. + cmsys::RegularExpression extractVersion( + "VCToolsVersion\\.([0-9.]+)\\.txt$"); + if (extractVersion.find(txt)) { + version = extractVersion.match(1); + } + } + } else { + props = cmStrCat(instancePath, "/VC/Auxiliary/Build/"_s); + return AuxToolset::PropsIndeterminate; + } } if (cmSystemTools::VersionCompareGreaterEq(version, "14.20")) { diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 23c365a..a1af268 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -468,6 +468,10 @@ bool cmGlobalXCodeGenerator::Open(const std::string& bindir, } CFRelease(cfStr); } +#else + (void)bindir; + (void)projectName; + (void)dryRun; #endif return ret; @@ -603,7 +607,6 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget( } #define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK" -#define OBJECT_LIBRARY_ARTIFACT_DIR std::string() void cmGlobalXCodeGenerator::AddExtraTargets( cmLocalGenerator* root, std::vector<cmLocalGenerator*>& gens) @@ -1188,13 +1191,9 @@ std::string GetTargetObjectDirArch(T const& target, std::string cmGlobalXCodeGenerator::GetLibraryOrFrameworkPath( const std::string& path) const { - auto fwItems = this->SplitFrameworkPath(path); - if (fwItems) { - if (fwItems->first.empty()) { - return cmStrCat(fwItems->second, ".framework"); - } else { - return cmStrCat(fwItems->first, '/', fwItems->second, ".framework"); - } + auto fwDescriptor = this->SplitFrameworkPath(path); + if (fwDescriptor) { + return fwDescriptor->GetFrameworkPath(); } return path; @@ -1372,6 +1371,18 @@ bool cmGlobalXCodeGenerator::CreateXCodeTarget( return true; } + for (std::string const& configName : this->CurrentConfigurationTypes) { + gtgt->CheckCxxModuleStatus(configName); + } + + if (gtgt->HaveCxx20ModuleSources()) { + gtgt->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The \"", gtgt->GetName(), + "\" target contains C++ module sources which are not " + "supported by the generator")); + } + auto& gtgt_visited = this->CommandsVisited[gtgt]; auto& deps = this->GetTargetDirectDepends(gtgt); for (auto& d : deps) { @@ -2352,8 +2363,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, std::string& flags = cflags[lang]; // Add language-specific flags. - this->CurrentLocalGenerator->AddLanguageFlags(flags, gtgt, lang, - configName); + this->CurrentLocalGenerator->AddLanguageFlags( + flags, gtgt, cmBuildStep::Compile, lang, configName); if (gtgt->IsIPOEnabled(lang, configName)) { this->CurrentLocalGenerator->AppendFeatureOptions(flags, lang, "IPO"); @@ -2412,6 +2423,18 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, this->AppendDefines(ppDefs, targetDefines); buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList()); + if (languages.count("Swift")) { + if (this->XcodeVersion < 80) { + std::string defineString; + std::set<std::string> defines(targetDefines.begin(), + targetDefines.end()); + this->CurrentLocalGenerator->JoinDefines(defines, defineString, "Swift"); + cflags["Swift"] += " " + defineString; + } else { + buildSettings->AddAttribute("SWIFT_ACTIVE_COMPILATION_CONDITIONS", + ppDefs.CreateList()); + } + } std::string extraLinkOptionsVar; std::string extraLinkOptions; @@ -2499,18 +2522,28 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, soName += *soversion; } + if (gtgt->CanCompileSources()) { + std::string tmpDir = + cmStrCat(gtgt->GetSupportDirectory(), '/', this->GetCMakeCFGIntDir()); + buildSettings->AddAttribute("TARGET_TEMP_DIR", this->CreateString(tmpDir)); + + std::string outDir; + if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) { + // We cannot suppress the archive, so hide it with intermediate files. + outDir = tmpDir; + } else { + outDir = gtgt->GetDirectory(configName); + } + buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", + this->CreateString(outDir)); + } + // Set attributes to specify the proper name for the target. std::string pndir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory(); if (gtgt->GetType() == cmStateEnums::STATIC_LIBRARY || gtgt->GetType() == cmStateEnums::SHARED_LIBRARY || gtgt->GetType() == cmStateEnums::MODULE_LIBRARY || gtgt->GetType() == cmStateEnums::EXECUTABLE) { - if (!gtgt->UsesDefaultOutputDir(configName, - cmStateEnums::RuntimeBinaryArtifact)) { - std::string pncdir = gtgt->GetDirectory(configName); - buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", - this->CreateString(pncdir)); - } if (gtgt->IsFrameworkOnApple() || gtgt->IsCFBundleOnApple()) { pnprefix = ""; @@ -2520,20 +2553,10 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, this->CreateString(pnprefix)); buildSettings->AddAttribute("EXECUTABLE_SUFFIX", this->CreateString(pnsuffix)); - } else if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) { - pnprefix = "lib"; - pnbase = gtgt->GetName(); - pnsuffix = ".a"; - - std::string pncdir = this->GetObjectsDirectory( - this->CurrentProject, configName, gtgt, OBJECT_LIBRARY_ARTIFACT_DIR); - buildSettings->AddAttribute("CONFIGURATION_BUILD_DIR", - this->CreateString(pncdir)); } // Store the product name for all target types. buildSettings->AddAttribute("PRODUCT_NAME", this->CreateString(realName)); - buildSettings->AddAttribute("SYMROOT", this->CreateString(pndir)); // Handle settings for each target type. switch (gtgt->GetType()) { @@ -2871,8 +2894,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, } // Create the INSTALL_PATH attribute. - std::string install_name_dir; if (gtgt->GetType() == cmStateEnums::SHARED_LIBRARY) { + std::string install_name_dir; // Get the install_name directory for the build tree. install_name_dir = gtgt->GetInstallNameDirForBuildTree(configName); // Xcode doesn't create the correct install_name in some cases. @@ -2894,9 +2917,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, extraLinkOptions += " -install_name "; extraLinkOptions += XCodeEscapePath(install_name); } + buildSettings->AddAttribute("INSTALL_PATH", + this->CreateString(install_name_dir)); } - buildSettings->AddAttribute("INSTALL_PATH", - this->CreateString(install_name_dir)); // Create the LD_RUNPATH_SEARCH_PATHS cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName); @@ -3618,9 +3641,10 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) linkDir = libItem->Value.Value; } if (cmHasSuffix(libItem->GetFeatureName(), "FRAMEWORK"_s)) { - auto fwItems = this->SplitFrameworkPath(linkDir, true); - if (fwItems && !fwItems->first.empty()) { - linkDir = std::move(fwItems->first); + auto fwDescriptor = this->SplitFrameworkPath( + linkDir, cmGlobalGenerator::FrameworkFormat::Extended); + if (fwDescriptor && !fwDescriptor->Directory.empty()) { + linkDir = fwDescriptor->Directory; if (std::find(frameworkSearchPaths.begin(), frameworkSearchPaths.end(), linkDir) == frameworkSearchPaths.end()) { frameworkSearchPaths.push_back(linkDir); @@ -3753,14 +3777,20 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) // add the library search paths { BuildObjectListOrString libSearchPaths(this, true); + std::string linkDirs; for (auto const& libDir : cli->GetDirectories()) { if (!libDir.empty() && libDir != "/usr/lib") { - libSearchPaths.Add(this->XCodeEscapePath( - libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)")); + cmPolicies::PolicyStatus cmp0142 = + target->GetTarget()->GetPolicyStatusCMP0142(); + if (cmp0142 == cmPolicies::OLD || cmp0142 == cmPolicies::WARN) { + libSearchPaths.Add(this->XCodeEscapePath( + libDir + "/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)")); + } libSearchPaths.Add(this->XCodeEscapePath(libDir)); } } + // Add previously collected paths where to look for libraries // that were added to "Link Binary With Libraries" for (auto& libDir : linkSearchPaths) { @@ -3800,6 +3830,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) const auto& fwPaths = cli->GetFrameworkPaths(); emitted.insert(fwPaths.begin(), fwPaths.end()); BuildObjectListOrString libPaths(this, true); + BuildObjectListOrString fwSearchPaths(this, true); for (auto const& libItem : configItemMap[configName]) { auto const& libName = *libItem; if (libName.IsPath == cmComputeLinkInformation::ItemIsPath::Yes) { @@ -3810,13 +3841,14 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) bool isFramework = cmHasSuffix(libName.GetFeatureName(), "FRAMEWORK"_s); if (isFramework) { - const auto fwItems = - this->SplitFrameworkPath(cleanPath, isFramework); - if (!fwItems->first.empty() && - emitted.insert(fwItems->first).second) { + const auto fwDescriptor = this->SplitFrameworkPath( + cleanPath, cmGlobalGenerator::FrameworkFormat::Extended); + if (!fwDescriptor->Directory.empty() && + emitted.insert(fwDescriptor->Directory).second) { // This is a search path we had not added before and it isn't // an implicit search path, so we need it - libPaths.Add("-F " + this->XCodeEscapePath(fwItems->first)); + fwSearchPaths.Add( + this->XCodeEscapePath(fwDescriptor->Directory)); } if (libName.GetFeatureName() == "__CMAKE_LINK_FRAMEWORK"_s) { // use the full path @@ -3824,10 +3856,10 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) libName.GetFormattedItem(this->XCodeEscapePath(cleanPath)) .Value); } else { - libPaths.Add( - libName - .GetFormattedItem(this->XCodeEscapePath(fwItems->second)) - .Value); + libPaths.Add(libName + .GetFormattedItem(this->XCodeEscapePath( + fwDescriptor->GetLinkName())) + .Value); } } else { libPaths.Add( @@ -3855,9 +3887,16 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) target->AddDependTarget(configName, libName.Target->GetName()); } } - this->AppendBuildSettingAttribute(target, - this->GetTargetLinkFlagsVar(gt), - libPaths.CreateList(), configName); + if (!libPaths.IsEmpty()) { + this->AppendBuildSettingAttribute(target, + this->GetTargetLinkFlagsVar(gt), + libPaths.CreateList(), configName); + } + if (!fwSearchPaths.IsEmpty()) { + this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS", + fwSearchPaths.CreateList(), + configName); + } } } } @@ -4438,16 +4477,6 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( return true; } -std::string cmGlobalXCodeGenerator::GetObjectsDirectory( - const std::string& projName, const std::string& configName, - const cmGeneratorTarget* t, const std::string& variant) const -{ - std::string dir = cmStrCat( - t->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', projName, - ".build/", configName, '/', t->GetName(), ".build/", variant); - return dir; -} - void cmGlobalXCodeGenerator::ComputeArchitectures(cmMakefile* mf) { this->Architectures.clear(); @@ -4571,10 +4600,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackMakefile( for (auto objLib : objlibs) { const std::string objLibName = objLib->GetName(); - std::string d = cmStrCat( - this->GetObjectsDirectory(this->CurrentProject, configName, objLib, - OBJECT_LIBRARY_ARTIFACT_DIR), - "lib", objLibName, ".a"); + std::string d = cmStrCat(objLib->GetSupportDirectory(), '/', + configName, "/lib", objLibName, ".a"); std::string dependency = this->ConvertToRelativeForMake(d); makefileStream << "\\\n\t" << dependency; @@ -4588,8 +4615,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackMakefile( // if building for more than one architecture // then remove those executables as well if (this->Architectures.size() > 1) { - std::string universal = this->GetObjectsDirectory( - this->CurrentProject, configName, gt, "$(OBJDIR)/"); + std::string universal = cmStrCat(gt->GetSupportDirectory(), '/', + configName, "/$(OBJDIR)/"); for (const auto& architecture : this->Architectures) { std::string universalFile = cmStrCat(universal, architecture, '/', gt->GetFullName(configName)); @@ -4986,14 +5013,10 @@ bool cmGlobalXCodeGenerator::ShouldStripResourcePath(cmMakefile*) const void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { - std::string configName = this->GetCMakeCFGIntDir(); auto objectDirArch = GetTargetObjectDirArch(*gt, this->ObjectDirArch); - - std::string dir = - cmStrCat(this->GetObjectsDirectory("$(PROJECT_NAME)", configName, gt, - "$(OBJECT_FILE_DIR_normal:base)/"), - objectDirArch, '/'); - gt->ObjectDirectory = dir; + gt->ObjectDirectory = + cmStrCat(gt->GetSupportDirectory(), '/', this->GetCMakeCFGIntDir(), + "/$(OBJECT_FILE_DIR_normal:base)/", objectDirArch, '/'); } std::string cmGlobalXCodeGenerator::GetDeploymentPlatform(const cmMakefile* mf) diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 92e4528..e924169 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -339,11 +339,6 @@ private: std::string GetLibraryOrFrameworkPath(const std::string& path) const; - std::string GetObjectsDirectory(const std::string& projName, - const std::string& configName, - const cmGeneratorTarget* t, - const std::string& variant) const; - static std::string GetDeploymentPlatform(const cmMakefile* mf); void ComputeArchitectures(cmMakefile* mf); diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 0da72b1..c2a09c1 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -150,7 +150,7 @@ bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, cmExecutionStatus status(mf); mf.ExecuteCommand(func, status); if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); + inStatus.SetReturnInvoked(status.GetReturnVariables()); return true; } if (status.GetBreakInvoked()) { diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 7ca5b23..82adca8 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -12,18 +12,22 @@ #include <utility> #include <cm/memory> +#include <cm/optional> #include <cm/string_view> #include <cmext/string_view> #include "cmsys/Glob.hxx" #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" #include "cmExecutionStatus.h" +#include "cmExperimental.h" #include "cmExportSet.h" #include "cmFileSet.h" #include "cmGeneratorExpression.h" #include "cmGlobalGenerator.h" #include "cmInstallCommandArguments.h" +#include "cmInstallCxxModuleBmiGenerator.h" #include "cmInstallDirectoryGenerator.h" #include "cmInstallExportGenerator.h" #include "cmInstallFileSetGenerator.h" @@ -54,13 +58,13 @@ namespace { struct RuntimeDependenciesArgs { - std::vector<std::string> Directories; - std::vector<std::string> PreIncludeRegexes; - std::vector<std::string> PreExcludeRegexes; - std::vector<std::string> PostIncludeRegexes; - std::vector<std::string> PostExcludeRegexes; - std::vector<std::string> PostIncludeFiles; - std::vector<std::string> PostExcludeFiles; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Directories; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PreIncludeRegexes; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PreExcludeRegexes; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeRegexes; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeRegexes; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PostIncludeFiles; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PostExcludeFiles; }; auto const RuntimeDependenciesArgHelper = @@ -109,6 +113,8 @@ public: const cmInstallCommandArguments* args) const; std::string GetLibraryDestination( const cmInstallCommandArguments* args) const; + std::string GetCxxModulesBmiDestination( + const cmInstallCommandArguments* args) const; std::string GetIncludeDestination( const cmInstallCommandArguments* args) const; std::string GetSysconfDestination( @@ -401,16 +407,17 @@ bool HandleTargetsMode(std::vector<std::string> const& args, struct ArgVectors { - std::vector<std::string> Archive; - std::vector<std::string> Library; - std::vector<std::string> Runtime; - std::vector<std::string> Object; - std::vector<std::string> Framework; - std::vector<std::string> Bundle; - std::vector<std::string> Includes; - std::vector<std::string> PrivateHeader; - std::vector<std::string> PublicHeader; - std::vector<std::string> Resource; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Archive; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Library; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Runtime; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Object; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Framework; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Bundle; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Includes; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PrivateHeader; + ArgumentParser::MaybeEmpty<std::vector<std::string>> PublicHeader; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Resource; + ArgumentParser::MaybeEmpty<std::vector<std::string>> CxxModulesBmi; std::vector<std::vector<std::string>> FileSets; }; @@ -426,7 +433,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, .Bind("PRIVATE_HEADER"_s, &ArgVectors::PrivateHeader) .Bind("PUBLIC_HEADER"_s, &ArgVectors::PublicHeader) .Bind("RESOURCE"_s, &ArgVectors::Resource) - .Bind("FILE_SET"_s, &ArgVectors::FileSets); + .Bind("FILE_SET"_s, &ArgVectors::FileSets) + .Bind("CXX_MODULES_BMI"_s, &ArgVectors::CxxModulesBmi); std::vector<std::string> genericArgVector; ArgVectors const argVectors = argHelper.Parse(args, &genericArgVector); @@ -434,26 +442,25 @@ bool HandleTargetsMode(std::vector<std::string> const& args, // now parse the generic args (i.e. the ones not specialized on LIBRARY/ // ARCHIVE, RUNTIME etc. (see above) // These generic args also contain the targets and the export stuff - std::vector<std::string> targetList; + ArgumentParser::MaybeEmpty<std::vector<std::string>> targetList; std::string exports; - std::vector<std::string> runtimeDependenciesArgVector; + cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> + runtimeDependenciesArgVector; std::string runtimeDependencySetArg; std::vector<std::string> unknownArgs; - std::vector<std::string> parsedArgs; cmInstallCommandArguments genericArgs(helper.DefaultComponentName); genericArgs.Bind("TARGETS"_s, targetList); genericArgs.Bind("EXPORT"_s, exports); genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector); genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg); - genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs); + genericArgs.Parse(genericArgVector, &unknownArgs); bool success = genericArgs.Finalize(); - bool withRuntimeDependencies = - std::find(parsedArgs.begin(), parsedArgs.end(), "RUNTIME_DEPENDENCIES") != - parsedArgs.end(); RuntimeDependenciesArgs runtimeDependenciesArgs = - RuntimeDependenciesArgHelper.Parse(runtimeDependenciesArgVector, - &unknownArgs); + runtimeDependenciesArgVector + ? RuntimeDependenciesArgHelper.Parse(*runtimeDependenciesArgVector, + &unknownArgs) + : RuntimeDependenciesArgs(); cmInstallCommandArguments archiveArgs(helper.DefaultComponentName); cmInstallCommandArguments libraryArgs(helper.DefaultComponentName); @@ -467,6 +474,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, cmInstallCommandIncludesArgument includesArgs; std::vector<cmInstallCommandFileSetArguments> fileSetArgs( argVectors.FileSets.size(), { helper.DefaultComponentName }); + cmInstallCommandArguments cxxModuleBmiArgs(helper.DefaultComponentName); // now parse the args for specific parts of the target (e.g. LIBRARY, // RUNTIME, ARCHIVE etc. @@ -490,6 +498,15 @@ bool HandleTargetsMode(std::vector<std::string> const& args, fileSetArgs[i] = std::move(fileSetArg); } + bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled( + *helper.Makefile, cmExperimental::Feature::CxxModuleCMakeApi); + if (!supportCxx20FileSetTypes) { + std::copy(argVectors.CxxModulesBmi.begin(), argVectors.CxxModulesBmi.end(), + std::back_inserter(unknownArgs)); + } else { + cxxModuleBmiArgs.Parse(argVectors.CxxModulesBmi, &unknownArgs); + } + if (!unknownArgs.empty()) { // Unknown argument. status.SetError( @@ -510,6 +527,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, for (auto& fileSetArg : fileSetArgs) { fileSetArg.SetGenericArguments(&genericArgs); } + cxxModuleBmiArgs.SetGenericArguments(&genericArgs); success = success && archiveArgs.Finalize(); success = success && libraryArgs.Finalize(); @@ -523,6 +541,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args, for (auto& fileSetArg : fileSetArgs) { success = success && fileSetArg.Finalize(); } + if (supportCxx20FileSetTypes) { + success = success && cxxModuleBmiArgs.Finalize(); + } if (!success) { return false; @@ -536,7 +557,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, publicHeaderArgs.GetNamelinkOnly() || resourceArgs.GetNamelinkOnly() || std::any_of(fileSetArgs.begin(), fileSetArgs.end(), [](const cmInstallCommandFileSetArguments& fileSetArg) - -> bool { return fileSetArg.GetNamelinkOnly(); })) { + -> bool { return fileSetArg.GetNamelinkOnly(); }) || + cxxModuleBmiArgs.GetNamelinkOnly()) { status.SetError( "TARGETS given NAMELINK_ONLY option not in LIBRARY group. " "The NAMELINK_ONLY option may be specified only following LIBRARY."); @@ -548,7 +570,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, publicHeaderArgs.GetNamelinkSkip() || resourceArgs.GetNamelinkSkip() || std::any_of(fileSetArgs.begin(), fileSetArgs.end(), [](const cmInstallCommandFileSetArguments& fileSetArg) - -> bool { return fileSetArg.GetNamelinkSkip(); })) { + -> bool { return fileSetArg.GetNamelinkSkip(); }) || + cxxModuleBmiArgs.GetNamelinkSkip()) { status.SetError( "TARGETS given NAMELINK_SKIP option not in LIBRARY group. " "The NAMELINK_SKIP option may be specified only following LIBRARY."); @@ -564,7 +587,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, resourceArgs.HasNamelinkComponent() || std::any_of(fileSetArgs.begin(), fileSetArgs.end(), [](const cmInstallCommandFileSetArguments& fileSetArg) - -> bool { return fileSetArg.HasNamelinkComponent(); })) { + -> bool { return fileSetArg.HasNamelinkComponent(); }) || + cxxModuleBmiArgs.HasNamelinkComponent()) { status.SetError( "TARGETS given NAMELINK_COMPONENT option not in LIBRARY group. " "The NAMELINK_COMPONENT option may be specified only following " @@ -583,7 +607,8 @@ bool HandleTargetsMode(std::vector<std::string> const& args, !publicHeaderArgs.GetType().empty() || !resourceArgs.GetType().empty() || std::any_of(fileSetArgs.begin(), fileSetArgs.end(), [](const cmInstallCommandFileSetArguments& fileSetArg) - -> bool { return !fileSetArg.GetType().empty(); })) { + -> bool { return !fileSetArg.GetType().empty(); }) || + !cxxModuleBmiArgs.GetType().empty()) { status.SetError( "TARGETS given TYPE option. The TYPE option may only be specified in " " install(FILES) and install(DIRECTORIES)."); @@ -597,7 +622,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr; - if (withRuntimeDependencies) { + if (runtimeDependenciesArgVector) { if (!runtimeDependencySetArg.empty()) { status.SetError("TARGETS cannot have both RUNTIME_DEPENDENCIES and " "RUNTIME_DEPENDENCY_SET."); @@ -706,6 +731,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, bool installsPublicHeader = false; bool installsResource = false; std::vector<bool> installsFileSet(fileSetArgs.size(), false); + bool installsCxxModuleBmi = false; // Generate install script code to install the given targets. for (cmTarget* ti : targets) { @@ -722,6 +748,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, std::unique_ptr<cmInstallFilesGenerator> publicHeaderGenerator; std::unique_ptr<cmInstallFilesGenerator> resourceGenerator; std::vector<std::unique_ptr<cmInstallFileSetGenerator>> fileSetGenerators; + std::unique_ptr<cmInstallCxxModuleBmiGenerator> cxxModuleBmiGenerator; // Avoid selecting default destinations for PUBLIC_HEADER and // PRIVATE_HEADER if any artifacts are specified. @@ -760,6 +787,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, for (auto const& gen : fileSetGenerators) { te->FileSetGenerators[gen->GetFileSet()] = gen.get(); } + te->CxxModuleBmiGenerator = cxxModuleBmiGenerator.get(); target.AddInstallIncludeDirectories( *te, cmMakeRange(includesArgs.GetIncludeDirs())); te->NamelinkOnly = namelinkOnly; @@ -1105,6 +1133,19 @@ bool HandleTargetsMode(std::vector<std::string> const& args, } } + if (supportCxx20FileSetTypes && + !cxxModuleBmiArgs.GetDestination().empty()) { + cxxModuleBmiGenerator = cm::make_unique<cmInstallCxxModuleBmiGenerator>( + target.GetName(), + helper.GetCxxModulesBmiDestination(&cxxModuleBmiArgs), + cxxModuleBmiArgs.GetPermissions(), + cxxModuleBmiArgs.GetConfigurations(), cxxModuleBmiArgs.GetComponent(), + cmInstallGenerator::SelectMessageLevel(target.GetMakefile()), + cxxModuleBmiArgs.GetExcludeFromAll(), cxxModuleBmiArgs.GetOptional(), + helper.Makefile->GetBacktrace()); + target.SetHaveInstallRule(true); + } + // Add this install rule to an export if one was specified. if (!addTargetExport()) { return false; @@ -1121,6 +1162,7 @@ bool HandleTargetsMode(std::vector<std::string> const& args, installsPrivateHeader = installsPrivateHeader || privateHeaderGenerator; installsPublicHeader = installsPublicHeader || publicHeaderGenerator; installsResource = installsResource || resourceGenerator; + installsCxxModuleBmi = installsCxxModuleBmi || cxxModuleBmiGenerator; helper.Makefile->AddInstallGenerator(std::move(archiveGenerator)); helper.Makefile->AddInstallGenerator(std::move(libraryGenerator)); @@ -1135,9 +1177,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args, for (auto& gen : fileSetGenerators) { helper.Makefile->AddInstallGenerator(std::move(gen)); } + helper.Makefile->AddInstallGenerator(std::move(cxxModuleBmiGenerator)); } - if (withRuntimeDependencies && !runtimeDependencySet->Empty()) { + if (runtimeDependenciesArgVector && !runtimeDependencySet->Empty()) { AddInstallRuntimeDependenciesGenerator( helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs, std::move(runtimeDependenciesArgs), installsRuntime, installsLibrary, @@ -1192,6 +1235,10 @@ bool HandleTargetsMode(std::vector<std::string> const& args, fileSetArgs[i].GetComponent()); } } + if (installsCxxModuleBmi) { + helper.Makefile->GetGlobalGenerator()->AddInstallComponent( + cxxModuleBmiArgs.GetComponent()); + } return true; } @@ -1206,10 +1253,10 @@ bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args, struct ArgVectors { - std::vector<std::string> Library; - std::vector<std::string> Runtime; - std::vector<std::string> Framework; - std::vector<std::string> Bundle; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Library; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Runtime; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Framework; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Bundle; }; static auto const argHelper = cmArgumentParser<ArgVectors>{} @@ -1223,7 +1270,7 @@ bool HandleImportedRuntimeArtifactsMode(std::vector<std::string> const& args, // now parse the generic args (i.e. the ones not specialized on LIBRARY, // RUNTIME etc. (see above) - std::vector<std::string> targetList; + ArgumentParser::MaybeEmpty<std::vector<std::string>> targetList; std::string runtimeDependencySetArg; std::vector<std::string> unknownArgs; cmInstallCommandArguments genericArgs(helper.DefaultComponentName); @@ -1464,7 +1511,7 @@ bool HandleFilesMode(std::vector<std::string> const& args, // This is the FILES mode. bool programs = (args[0] == "PROGRAMS"); cmInstallCommandArguments ica(helper.DefaultComponentName); - std::vector<std::string> files; + ArgumentParser::MaybeEmpty<std::vector<std::string>> files; ica.Bind(programs ? "PROGRAMS"_s : "FILES"_s, files); std::vector<std::string> unknownArgs; ica.Parse(args, &unknownArgs); @@ -1950,7 +1997,7 @@ bool HandleExportAndroidMKMode(std::vector<std::string> const& args, cm::make_unique<cmInstallExportGenerator>( &exportSet, ica.GetDestination(), ica.GetPermissions(), ica.GetConfigurations(), ica.GetComponent(), message, - ica.GetExcludeFromAll(), fname, name_space, exportOld, true, + ica.GetExcludeFromAll(), fname, name_space, "", exportOld, true, helper.Makefile->GetBacktrace())); return true; @@ -1973,12 +2020,19 @@ bool HandleExportMode(std::vector<std::string> const& args, std::string name_space; bool exportOld = false; std::string filename; + std::string cxx_modules_directory; ica.Bind("EXPORT"_s, exp); ica.Bind("NAMESPACE"_s, name_space); ica.Bind("EXPORT_LINK_INTERFACE_LIBRARIES"_s, exportOld); ica.Bind("FILE"_s, filename); + bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled( + *helper.Makefile, cmExperimental::Feature::CxxModuleCMakeApi); + if (supportCxx20FileSetTypes) { + ica.Bind("CXX_MODULES_DIRECTORY"_s, cxx_modules_directory); + } + std::vector<std::string> unknownArgs; ica.Parse(args, &unknownArgs); @@ -2064,8 +2118,8 @@ bool HandleExportMode(std::vector<std::string> const& args, cm::make_unique<cmInstallExportGenerator>( &exportSet, ica.GetDestination(), ica.GetPermissions(), ica.GetConfigurations(), ica.GetComponent(), message, - ica.GetExcludeFromAll(), fname, name_space, exportOld, false, - helper.Makefile->GetBacktrace())); + ica.GetExcludeFromAll(), fname, name_space, cxx_modules_directory, + exportOld, false, helper.Makefile->GetBacktrace())); return true; } @@ -2088,9 +2142,9 @@ bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args, struct ArgVectors { - std::vector<std::string> Library; - std::vector<std::string> Runtime; - std::vector<std::string> Framework; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Library; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Runtime; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Framework; }; static auto const argHelper = cmArgumentParser<ArgVectors>{} @@ -2106,11 +2160,9 @@ bool HandleRuntimeDependencySetMode(std::vector<std::string> const& args, // These generic args also contain the runtime dependency set std::string runtimeDependencySetArg; std::vector<std::string> runtimeDependencyArgVector; - std::vector<std::string> parsedArgs; cmInstallCommandArguments genericArgs(helper.DefaultComponentName); genericArgs.Bind("RUNTIME_DEPENDENCY_SET"_s, runtimeDependencySetArg); - genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector, nullptr, - &parsedArgs); + genericArgs.Parse(genericArgVector, &runtimeDependencyArgVector); bool success = genericArgs.Finalize(); cmInstallCommandArguments libraryArgs(helper.DefaultComponentName); @@ -2280,6 +2332,15 @@ std::string Helper::GetLibraryDestination( return this->GetDestination(args, "CMAKE_INSTALL_LIBDIR", "lib"); } +std::string Helper::GetCxxModulesBmiDestination( + const cmInstallCommandArguments* args) const +{ + if (args) { + return args->GetDestination(); + } + return {}; +} + std::string Helper::GetIncludeDestination( const cmInstallCommandArguments* args) const { diff --git a/Source/cmInstallCommandArguments.h b/Source/cmInstallCommandArguments.h index 79bd945..6e46aac 100644 --- a/Source/cmInstallCommandArguments.h +++ b/Source/cmInstallCommandArguments.h @@ -8,6 +8,7 @@ #include <vector> #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" class cmInstallCommandArguments : public cmArgumentParser<void> { @@ -44,8 +45,8 @@ private: std::string NamelinkComponent; bool ExcludeFromAll = false; std::string Rename; - std::vector<std::string> Permissions; - std::vector<std::string> Configurations; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Permissions; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Configurations; bool Optional = false; bool NamelinkOnly = false; bool NamelinkSkip = false; diff --git a/Source/cmInstallCxxModuleBmiGenerator.cxx b/Source/cmInstallCxxModuleBmiGenerator.cxx new file mode 100644 index 0000000..1ef1eaa --- /dev/null +++ b/Source/cmInstallCxxModuleBmiGenerator.cxx @@ -0,0 +1,75 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmInstallCxxModuleBmiGenerator.h" + +#include <ostream> +#include <utility> + +#include "cmGeneratorExpression.h" +#include "cmGeneratorTarget.h" +#include "cmGlobalGenerator.h" +#include "cmListFileCache.h" +#include "cmLocalGenerator.h" +#include "cmOutputConverter.h" +#include "cmStringAlgorithms.h" + +cmInstallCxxModuleBmiGenerator::cmInstallCxxModuleBmiGenerator( + std::string target, std::string const& dest, std::string file_permissions, + std::vector<std::string> const& configurations, std::string const& component, + MessageLevel message, bool exclude_from_all, bool optional, + cmListFileBacktrace backtrace) + : cmInstallGenerator(dest, configurations, component, message, + exclude_from_all, false, std::move(backtrace)) + , TargetName(std::move(target)) + , FilePermissions(std::move(file_permissions)) + , Optional(optional) +{ + this->ActionsPerConfig = true; +} + +cmInstallCxxModuleBmiGenerator::~cmInstallCxxModuleBmiGenerator() = default; + +bool cmInstallCxxModuleBmiGenerator::Compute(cmLocalGenerator* lg) +{ + this->LocalGenerator = lg; + + this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName); + if (!this->Target) { + // If no local target has been found, find it in the global scope. + this->Target = + lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName); + } + + return true; +} + +std::string cmInstallCxxModuleBmiGenerator::GetScriptLocation( + std::string const& config) const +{ + char const* config_name = config.c_str(); + if (config.empty()) { + config_name = "noconfig"; + } + return cmStrCat(this->Target->GetSupportDirectory(), + "/install-cxx-module-bmi-", config_name, ".cmake"); +} + +std::string cmInstallCxxModuleBmiGenerator::GetDestination( + std::string const& config) const +{ + return cmGeneratorExpression::Evaluate(this->Destination, + this->LocalGenerator, config); +} + +void cmInstallCxxModuleBmiGenerator::GenerateScriptForConfig( + std::ostream& os, const std::string& config, Indent indent) +{ + auto const& loc = this->GetScriptLocation(config); + if (loc.empty()) { + return; + } + os << indent << "include(\"" + << cmOutputConverter::EscapeForCMake( + loc, cmOutputConverter::WrapQuotes::NoWrap) + << "\" OPTIONAL)\n"; +} diff --git a/Source/cmInstallCxxModuleBmiGenerator.h b/Source/cmInstallCxxModuleBmiGenerator.h new file mode 100644 index 0000000..21edb2e --- /dev/null +++ b/Source/cmInstallCxxModuleBmiGenerator.h @@ -0,0 +1,52 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#pragma once + +#include "cmConfigure.h" // IWYU pragma: keep + +#include <iosfwd> +#include <string> +#include <vector> + +#include "cmInstallGenerator.h" +#include "cmScriptGenerator.h" + +class cmGeneratorTarget; +class cmListFileBacktrace; +class cmLocalGenerator; + +/** \class cmInstallCxxModuleBmiGenerator + * \brief Generate C++ module BMI installation rules. + */ +class cmInstallCxxModuleBmiGenerator : public cmInstallGenerator +{ +public: + cmInstallCxxModuleBmiGenerator( + std::string target, std::string const& dest, std::string file_permissions, + std::vector<std::string> const& configurations, + std::string const& component, MessageLevel message, bool exclude_from_all, + bool optional, cmListFileBacktrace backtrace); + ~cmInstallCxxModuleBmiGenerator() override; + + bool Compute(cmLocalGenerator* lg) override; + + std::string const& GetFilePermissions() const + { + return this->FilePermissions; + } + std::string GetDestination(std::string const& config) const; + std::string GetScriptLocation(std::string const& config) const; + cmGeneratorTarget const* GetTarget() const { return this->Target; } + bool GetOptional() const { return this->Optional; } + MessageLevel GetMessageLevel() const { return this->Message; } + +protected: + void GenerateScriptForConfig(std::ostream& os, const std::string& config, + Indent indent) override; + + std::string const TargetName; + cmGeneratorTarget const* Target = nullptr; + cmLocalGenerator* LocalGenerator = nullptr; + std::string const FilePermissions; + bool const Optional; +}; diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx index b80437d..1d81b0b 100644 --- a/Source/cmInstallExportGenerator.cxx +++ b/Source/cmInstallExportGenerator.cxx @@ -23,7 +23,8 @@ cmInstallExportGenerator::cmInstallExportGenerator( cmExportSet* exportSet, std::string const& destination, std::string file_permissions, std::vector<std::string> const& configurations, std::string const& component, MessageLevel message, bool exclude_from_all, - std::string filename, std::string name_space, bool exportOld, bool android, + std::string filename, std::string name_space, + std::string cxx_modules_directory, bool exportOld, bool android, cmListFileBacktrace backtrace) : cmInstallGenerator(destination, configurations, component, message, exclude_from_all, false, std::move(backtrace)) @@ -31,6 +32,7 @@ cmInstallExportGenerator::cmInstallExportGenerator( , FilePermissions(std::move(file_permissions)) , FileName(std::move(filename)) , Namespace(std::move(name_space)) + , CxxModulesDirectory(std::move(cxx_modules_directory)) , ExportOld(exportOld) { if (android) { @@ -141,6 +143,75 @@ void cmInstallExportGenerator::GenerateScriptConfigs(std::ostream& os, os << indent << "endif()\n"; files.clear(); } + + // Now create a configuration-specific install rule for the C++ module import + // property file of each configuration. + auto cxx_module_dest = + cmStrCat(this->Destination, '/', this->CxxModulesDirectory); + std::string config_file_example; + for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) { + config_file_example = i.second; + break; + } + if (!config_file_example.empty()) { + // Remove old per-configuration export files if the main changes. + std::string installedDir = cmStrCat( + "$ENV{DESTDIR}", ConvertToAbsoluteDestination(cxx_module_dest), '/'); + std::string installedFile = cmStrCat(installedDir, "/cxx-modules.cmake"); + std::string toInstallFile = + cmStrCat(cmSystemTools::GetFilenamePath(config_file_example), + "/cxx-modules.cmake"); + os << indent << "if(EXISTS \"" << installedFile << "\")\n"; + Indent indentN = indent.Next(); + Indent indentNN = indentN.Next(); + Indent indentNNN = indentNN.Next(); + /* clang-format off */ + os << indentN << "file(DIFFERENT _cmake_export_file_changed FILES\n" + << indentN << " \"" << installedFile << "\"\n" + << indentN << " \"" << toInstallFile << "\")\n"; + os << indentN << "if(_cmake_export_file_changed)\n"; + os << indentNN << "file(GLOB _cmake_old_config_files \"" << installedDir + << this->EFGen->GetConfigImportFileGlob() << "\")\n"; + os << indentNN << "if(_cmake_old_config_files)\n"; + os << indentNNN << "string(REPLACE \";\" \", \" _cmake_old_config_files_text \"${_cmake_old_config_files}\")\n"; + os << indentNNN << R"(message(STATUS "Old C++ module export file \")" << installedFile + << "\\\" will be replaced. Removing files [${_cmake_old_config_files_text}].\")\n"; + os << indentNNN << "unset(_cmake_old_config_files_text)\n"; + os << indentNNN << "file(REMOVE ${_cmake_old_config_files})\n"; + os << indentNN << "endif()\n"; + os << indentNN << "unset(_cmake_old_config_files)\n"; + os << indentN << "endif()\n"; + os << indentN << "unset(_cmake_export_file_changed)\n"; + os << indent << "endif()\n"; + /* clang-format on */ + + // All of these files are siblings; get its location to know where the + // "anchor" file is. + files.push_back(toInstallFile); + this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files, + false, this->FilePermissions.c_str(), nullptr, + nullptr, nullptr, indent); + files.clear(); + } + for (auto const& i : this->EFGen->GetConfigCxxModuleFiles()) { + files.push_back(i.second); + std::string config_test = this->CreateConfigTest(i.first); + os << indent << "if(" << config_test << ")\n"; + this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, files, + false, this->FilePermissions.c_str(), nullptr, + nullptr, nullptr, indent.Next()); + os << indent << "endif()\n"; + files.clear(); + } + for (auto const& i : this->EFGen->GetConfigCxxModuleTargetFiles()) { + std::string config_test = this->CreateConfigTest(i.first); + os << indent << "if(" << config_test << ")\n"; + this->AddInstallRule(os, cxx_module_dest, cmInstallType_FILES, i.second, + false, this->FilePermissions.c_str(), nullptr, + nullptr, nullptr, indent.Next()); + os << indent << "endif()\n"; + files.clear(); + } } void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os, diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h index 02fe1fa..346ca67 100644 --- a/Source/cmInstallExportGenerator.h +++ b/Source/cmInstallExportGenerator.h @@ -28,7 +28,8 @@ public: const std::vector<std::string>& configurations, std::string const& component, MessageLevel message, bool exclude_from_all, std::string filename, - std::string name_space, bool exportOld, + std::string name_space, + std::string cxx_modules_directory, bool exportOld, bool android, cmListFileBacktrace backtrace); cmInstallExportGenerator(const cmInstallExportGenerator&) = delete; ~cmInstallExportGenerator() override; @@ -50,6 +51,10 @@ public: std::string GetDestinationFile() const; std::string GetFileName() const { return this->FileName; } std::string GetTempDir() const; + std::string GetCxxModuleDirectory() const + { + return this->CxxModulesDirectory; + } protected: void GenerateScript(std::ostream& os) override; @@ -64,6 +69,7 @@ protected: std::string const FilePermissions; std::string const FileName; std::string const Namespace; + std::string const CxxModulesDirectory; bool const ExportOld; cmLocalGenerator* LocalGenerator = nullptr; diff --git a/Source/cmLinkLineDeviceComputer.cxx b/Source/cmLinkLineDeviceComputer.cxx index 43f1b8e..b06dc3d 100644 --- a/Source/cmLinkLineDeviceComputer.cxx +++ b/Source/cmLinkLineDeviceComputer.cxx @@ -57,7 +57,6 @@ bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking( // For this we only consider targets using ItemVector = cmComputeLinkInformation::ItemVector; ItemVector const& items = cli.GetItems(); - std::string config = cli.GetConfig(); return std::any_of( items.begin(), items.end(), [](cmComputeLinkInformation::Item const& item) -> bool { @@ -69,6 +68,26 @@ bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinking( }); } +bool cmLinkLineDeviceComputer::ComputeRequiresDeviceLinkingIPOFlag( + cmComputeLinkInformation& cli) +{ + // Determine if this item might requires device linking. + // For this we only consider targets + using ItemVector = cmComputeLinkInformation::ItemVector; + ItemVector const& items = cli.GetItems(); + std::string config = cli.GetConfig(); + return std::any_of( + items.begin(), items.end(), + [config](cmComputeLinkInformation::Item const& item) -> bool { + return item.Target && + item.Target->GetType() == cmStateEnums::STATIC_LIBRARY && + // this dependency requires us to device link it + !item.Target->GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS") && + item.Target->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION") && + item.Target->IsIPOEnabled("CUDA", config); + }); +} + void cmLinkLineDeviceComputer::ComputeLinkLibraries( cmComputeLinkInformation& cli, std::string const& stdLibString, std::vector<BT<std::string>>& linkLibraries) diff --git a/Source/cmLinkLineDeviceComputer.h b/Source/cmLinkLineDeviceComputer.h index dee625b..0916307 100644 --- a/Source/cmLinkLineDeviceComputer.h +++ b/Source/cmLinkLineDeviceComputer.h @@ -30,6 +30,7 @@ public: delete; bool ComputeRequiresDeviceLinking(cmComputeLinkInformation& cli); + bool ComputeRequiresDeviceLinkingIPOFlag(cmComputeLinkInformation& cli); void ComputeLinkLibraries( cmComputeLinkInformation& cli, std::string const& stdLibString, diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index 91157cb..6270c82 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -347,6 +347,7 @@ enum class NestingStateEnum Foreach, Function, Macro, + Block }; struct NestingState @@ -434,6 +435,16 @@ cm::optional<cmListFileContext> cmListFileParser::CheckNesting() const return cmListFileContext::FromListFileFunction(func, this->FileName); } stack.pop_back(); + } else if (name == "block") { + stack.push_back({ + NestingStateEnum::Block, + cmListFileContext::FromListFileFunction(func, this->FileName), + }); + } else if (name == "endblock") { + if (!TopIs(stack, NestingStateEnum::Block)) { + return cmListFileContext::FromListFileFunction(func, this->FileName); + } + stack.pop_back(); } } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 99bd05f..2a50dd3 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -15,6 +15,7 @@ #include <vector> #include <cm/memory> +#include <cm/optional> #include <cm/string_view> #include <cmext/algorithm> #include <cmext/string_view> @@ -36,6 +37,7 @@ #include "cmInstallScriptGenerator.h" #include "cmInstallTargetGenerator.h" #include "cmLinkLineComputer.h" +#include "cmLinkLineDeviceComputer.h" #include "cmMakefile.h" #include "cmRange.h" #include "cmRulePlaceholderExpander.h" @@ -1385,7 +1387,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetStaticLibraryFlags( } void cmLocalGenerator::GetDeviceLinkFlags( - cmLinkLineComputer& linkLineComputer, const std::string& config, + cmLinkLineDeviceComputer& linkLineComputer, const std::string& config, std::string& linkLibs, std::string& linkFlags, std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget* target) { @@ -1393,6 +1395,18 @@ void cmLocalGenerator::GetDeviceLinkFlags( cmComputeLinkInformation* pcli = target->GetLinkInformation(config); + auto linklang = linkLineComputer.GetLinkerLanguage(target, config); + auto ipoEnabled = target->IsIPOEnabled(linklang, config); + if (!ipoEnabled) { + ipoEnabled = linkLineComputer.ComputeRequiresDeviceLinkingIPOFlag(*pcli); + } + if (ipoEnabled) { + if (cmValue cudaIPOFlags = this->Makefile->GetDefinition( + "CMAKE_CUDA_DEVICE_LINK_OPTIONS_IPO")) { + linkFlags += cudaIPOFlags; + } + } + if (pcli) { // Compute the required device link libraries when // resolving gpu lang device symbols @@ -1400,6 +1414,8 @@ void cmLocalGenerator::GetDeviceLinkFlags( linkPath); } + // iterate link deps and see if any of them need IPO + std::vector<std::string> linkOpts; target->GetLinkOptions(linkOpts, config, "CUDA"); // LINK_OPTIONS are escaped. @@ -1594,7 +1610,8 @@ std::vector<BT<std::string>> cmLocalGenerator::GetTargetCompileFlags( cmMakefile* mf = this->GetMakefile(); // Add language-specific flags. - this->AddLanguageFlags(compileFlags, target, lang, config); + this->AddLanguageFlags(compileFlags, target, cmBuildStep::Compile, lang, + config); if (target->IsIPOEnabled(lang, config)) { this->AppendFeatureOptions(compileFlags, lang, "IPO"); @@ -1907,6 +1924,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, void cmLocalGenerator::AddLanguageFlags(std::string& flags, cmGeneratorTarget const* target, + cmBuildStep compileOrLink, const std::string& lang, const std::string& config) { @@ -1930,7 +1948,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, } } } else if (lang == "CUDA") { - target->AddCUDAArchitectureFlags(flags); + target->AddCUDAArchitectureFlags(compileOrLink, config, flags); target->AddCUDAToolkitFlags(flags); } else if (lang == "ISPC") { target->AddISPCTargetFlags(flags); @@ -2027,6 +2045,41 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags, } } } + + // Add MSVC debug information format flags. This is activated by the presence + // of a default selection whether or not it is overridden by a property. + cmValue msvcDebugInformationFormatDefault = this->Makefile->GetDefinition( + "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT"); + if (cmNonempty(msvcDebugInformationFormatDefault)) { + cmValue msvcDebugInformationFormatValue = + target->GetProperty("MSVC_DEBUG_INFORMATION_FORMAT"); + if (!msvcDebugInformationFormatValue) { + msvcDebugInformationFormatValue = msvcDebugInformationFormatDefault; + } + std::string const msvcDebugInformationFormat = + cmGeneratorExpression::Evaluate(*msvcDebugInformationFormatValue, this, + config, target); + if (!msvcDebugInformationFormat.empty()) { + if (cmValue msvcDebugInformationFormatOptions = + this->Makefile->GetDefinition( + cmStrCat("CMAKE_", lang, + "_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_", + msvcDebugInformationFormat))) { + this->AppendCompileOptions(flags, *msvcDebugInformationFormatOptions); + } else if ((this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_COMPILER_ID")) == "MSVC"_s || + this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_SIMULATE_ID")) == "MSVC"_s) && + !cmSystemTools::GetErrorOccurredFlag()) { + // The compiler uses the MSVC ABI so it needs a known runtime library. + this->IssueMessage(MessageType::FATAL_ERROR, + cmStrCat("MSVC_DEBUG_INFORMATION_FORMAT value '", + msvcDebugInformationFormat, + "' not known for this ", lang, + " compiler.")); + } + } + } } void cmLocalGenerator::AddLanguageFlagsForLinking( @@ -2042,7 +2095,7 @@ void cmLocalGenerator::AddLanguageFlagsForLinking( this->AddCompilerRequirementFlag(flags, target, lang, config); } - this->AddLanguageFlags(flags, target, lang, config); + this->AddLanguageFlags(flags, target, cmBuildStep::Link, lang, config); if (target->IsIPOEnabled(lang, config)) { this->AppendFeatureOptions(flags, lang, "IPO"); @@ -2578,7 +2631,9 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) if (pchSource.empty() || pchHeader.empty()) { if (this->GetGlobalGenerator()->IsXcode() && !pchLangSet.empty()) { for (auto* sf : sources) { - if (pchLangSet.find(sf->GetLanguage()) == pchLangSet.end()) { + const auto sourceLanguage = sf->GetLanguage(); + if (!sourceLanguage.empty() && + pchLangSet.find(sourceLanguage) == pchLangSet.end()) { sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON"); } } @@ -2671,7 +2726,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) cmStrCat(linkerProperty, configUpper), cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)), - true); + cm::nullopt, true); } else if (reuseTarget->GetType() == cmStateEnums::OBJECT_LIBRARY) { // FIXME: This can propagate more than one level, unlike diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 7cae1fc..0529431 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -35,6 +35,7 @@ class cmGeneratorTarget; class cmGlobalGenerator; class cmImplicitDependsList; class cmLinkLineComputer; +class cmLinkLineDeviceComputer; class cmMakefile; class cmRulePlaceholderExpander; class cmSourceFile; @@ -59,6 +60,13 @@ enum class cmDependencyScannerKind Compiler }; +/** What to compute language flags for */ +enum class cmBuildStep +{ + Compile, + Link +}; + /** Target and source file which have a specific output. */ struct cmSourcesWithOutput { @@ -143,7 +151,8 @@ public: const std::string& filterArch = std::string()); void AddLanguageFlags(std::string& flags, cmGeneratorTarget const* target, - const std::string& lang, const std::string& config); + cmBuildStep compileOrLink, const std::string& lang, + const std::string& config); void AddLanguageFlagsForLinking(std::string& flags, cmGeneratorTarget const* target, const std::string& lang, @@ -476,7 +485,7 @@ public: /** Fill out these strings for the given target. Libraries to link, * flags, and linkflags. */ - void GetDeviceLinkFlags(cmLinkLineComputer& linkLineComputer, + void GetDeviceLinkFlags(cmLinkLineDeviceComputer& linkLineComputer, const std::string& config, std::string& linkLibs, std::string& linkFlags, std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget* target); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index e125470..de1d3cd 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1412,13 +1412,16 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) { // The dependencies must be regenerated. - std::string targetName = cmSystemTools::GetFilenameName(targetDir); - targetName = targetName.substr(0, targetName.length() - 4); - std::string message = - cmStrCat("Scanning dependencies of target ", targetName); - cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta | - cmsysTerminal_Color_ForegroundBold, - message.c_str(), true, color); + if (verbose) { + std::string targetName = cmSystemTools::GetFilenameName(targetDir); + targetName = targetName.substr(0, targetName.length() - 4); + std::string message = + cmStrCat("Scanning dependencies of target ", targetName); + cmSystemTools::MakefileColorEcho( + cmsysTerminal_Color_ForegroundMagenta | + cmsysTerminal_Color_ForegroundBold, + message.c_str(), true, color); + } status = this->ScanDependencies(targetDir, dependFile, internalDependFile, validDependencies); @@ -1447,13 +1450,19 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( this->GetBinaryDirectory()) : std::function<bool(const std::string&)>())) { // regenerate dependencies files - std::string targetName = - cmCMakePath(targetDir).GetFileName().RemoveExtension().GenericString(); - auto message = cmStrCat( - "Consolidate compiler generated dependencies of target ", targetName); - cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta | - cmsysTerminal_Color_ForegroundBold, - message.c_str(), true, color); + if (verbose) { + std::string targetName = cmCMakePath(targetDir) + .GetFileName() + .RemoveExtension() + .GenericString(); + auto message = + cmStrCat("Consolidate compiler generated dependencies of target ", + targetName); + cmSystemTools::MakefileColorEcho( + cmsysTerminal_Color_ForegroundMagenta | + cmsysTerminal_Color_ForegroundBold, + message.c_str(), true, color); + } // Open the make depends file. This should be copy-if-different // because the make tool may try to reload it needlessly otherwise. diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h index 75fe262..7bfe3b7 100644 --- a/Source/cmLocalVisualStudio10Generator.h +++ b/Source/cmLocalVisualStudio10Generator.h @@ -15,8 +15,8 @@ class cmMakefile; /** \class cmLocalVisualStudio10Generator * \brief Write Visual Studio 10 project files. * - * cmLocalVisualStudio10Generator produces a Visual Studio 10 project - * file for each target in its directory. + * cmLocalVisualStudio10Generator produces a MSBuild project file for each + * target in its directory. */ class cmLocalVisualStudio10Generator : public cmLocalVisualStudio7Generator { diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index f65add1..af2d31d 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -195,10 +195,10 @@ void cmLocalVisualStudio7Generator::GenerateTarget(cmGeneratorTarget* target) this->FortranProject = gg->TargetIsFortranOnly(target); this->WindowsCEProject = gg->TargetsWindowsCE(); - // Intel Fortran for VS10 uses VS9 format ".vfproj" files. + // Intel Fortran always uses VS9 format ".vfproj" files. cmGlobalVisualStudioGenerator::VSVersion realVersion = gg->GetVersion(); if (this->FortranProject && - gg->GetVersion() >= cmGlobalVisualStudioGenerator::VSVersion::VS10) { + gg->GetVersion() >= cmGlobalVisualStudioGenerator::VSVersion::VS11) { gg->SetVersion(cmGlobalVisualStudioGenerator::VSVersion::VS9); } @@ -680,7 +680,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( langForClCompile = linkLanguage; if (langForClCompile == "C" || langForClCompile == "CXX" || langForClCompile == "Fortran") { - this->AddLanguageFlags(flags, target, langForClCompile, configName); + this->AddLanguageFlags(flags, target, cmBuildStep::Compile, + langForClCompile, configName); } // set the correct language if (linkLanguage == "C") { diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx index ef12487..47ad749 100644 --- a/Source/cmMacroCommand.cxx +++ b/Source/cmMacroCommand.cxx @@ -126,7 +126,7 @@ bool cmMacroHelperCommand::operator()( return false; } if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); + inStatus.SetReturnInvoked(status.GetReturnVariables()); return true; } if (status.GetBreakInvoked()) { diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 469eac3..6e0d704 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -149,6 +149,29 @@ void cmMakefile::IssueMessage(MessageType t, std::string const& text) const this->GetCMakeInstance()->IssueMessage(t, text, this->Backtrace); } +Message::LogLevel cmMakefile::GetCurrentLogLevel() const +{ + const cmake* cmakeInstance = this->GetCMakeInstance(); + + const Message::LogLevel logLevelCliOrDefault = cmakeInstance->GetLogLevel(); + assert("Expected a valid log level here" && + logLevelCliOrDefault != Message::LogLevel::LOG_UNDEFINED); + + Message::LogLevel result = logLevelCliOrDefault; + + // If the log-level was set via the command line option, it takes precedence + // over the CMAKE_MESSAGE_LOG_LEVEL variable. + if (!cmakeInstance->WasLogLevelSetViaCLI()) { + const Message::LogLevel logLevelFromVar = cmake::StringToLogLevel( + this->GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL")); + if (logLevelFromVar != Message::LogLevel::LOG_UNDEFINED) { + result = logLevelFromVar; + } + } + + return result; +} + bool cmMakefile::CheckCMP0037(std::string const& targetName, cmStateEnums::TargetType targetType) const { @@ -766,6 +789,7 @@ void cmMakefile::RunListFile(cmListFile const& listFile, break; } if (status.GetReturnInvoked()) { + this->RaiseScope(status.GetReturnVariables()); // Exit early due to return command. break; } @@ -1759,7 +1783,8 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf) void cmMakefile::AddSubDirectory(const std::string& srcPath, const std::string& binPath, - bool excludeFromAll, bool immediate) + bool excludeFromAll, bool immediate, + bool system) { if (this->DeferRunning) { this->IssueMessage( @@ -1789,6 +1814,9 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, if (excludeFromAll) { subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } + if (system) { + subMf->SetProperty("SYSTEM", "TRUE"); + } if (immediate) { this->ConfigureSubDirectory(subMf); @@ -3456,7 +3484,7 @@ void cmMakefile::AddTargetObject(std::string const& tgtName, #endif } -void cmMakefile::EnableLanguage(std::vector<std::string> const& lang, +void cmMakefile::EnableLanguage(std::vector<std::string> const& languages, bool optional) { if (this->DeferRunning) { @@ -3468,24 +3496,48 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const& lang, if (const char* def = this->GetGlobalGenerator()->GetCMakeCFGIntDir()) { this->AddDefinition("CMAKE_CFG_INTDIR", def); } + + std::vector<std::string> unique_languages; + { + std::vector<std::string> duplicate_languages; + for (std::string const& language : languages) { + if (!cm::contains(unique_languages, language)) { + unique_languages.push_back(language); + } else if (!cm::contains(duplicate_languages, language)) { + duplicate_languages.push_back(language); + } + } + if (!duplicate_languages.empty()) { + auto quantity = duplicate_languages.size() == 1 ? std::string(" has") + : std::string("s have"); + this->IssueMessage(MessageType::AUTHOR_WARNING, + "Languages to be enabled may not be specified more " + "than once at the same time. The following language" + + quantity + " been specified multiple times: " + + cmJoin(duplicate_languages, ", ")); + } + } + // If RC is explicitly listed we need to do it after other languages. // On some platforms we enable RC implicitly while enabling others. // Do not let that look like recursive enable_language(RC). - std::vector<std::string> langs; - std::vector<std::string> langsRC; - langs.reserve(lang.size()); - for (std::string const& i : lang) { - if (i == "RC") { - langsRC.push_back(i); + std::vector<std::string> languages_without_RC; + std::vector<std::string> languages_for_RC; + languages_without_RC.reserve(unique_languages.size()); + for (std::string const& language : unique_languages) { + if (language == "RC") { + languages_for_RC.push_back(language); } else { - langs.push_back(i); + languages_without_RC.push_back(language); } } - if (!langs.empty()) { - this->GetGlobalGenerator()->EnableLanguage(langs, this, optional); + if (!languages_without_RC.empty()) { + this->GetGlobalGenerator()->EnableLanguage(languages_without_RC, this, + optional); } - if (!langsRC.empty()) { - this->GetGlobalGenerator()->EnableLanguage(langsRC, this, optional); + if (!languages_for_RC.empty()) { + this->GetGlobalGenerator()->EnableLanguage(languages_for_RC, this, + optional); } } @@ -4116,6 +4168,18 @@ void cmMakefile::RaiseScope(const std::string& var, const char* varDef) #endif } +void cmMakefile::RaiseScope(const std::vector<std::string>& variables) +{ + for (auto const& varName : variables) { + if (this->IsNormalDefinitionSet(varName)) { + this->RaiseScope(varName, this->GetDefinition(varName)); + } else { + // unset variable in parent scope + this->RaiseScope(varName, nullptr); + } + } +} + cmTarget* cmMakefile::AddImportedTarget(const std::string& name, cmStateEnums::TargetType type, bool global) @@ -4406,7 +4470,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, } // Deprecate old policies. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0097 && + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0102 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. @@ -4471,6 +4535,19 @@ bool cmMakefile::SetPolicyVersion(std::string const& version_min, cmPolicies::WarnCompat::On); } +cmMakefile::VariablePushPop::VariablePushPop(cmMakefile* m) + : Makefile(m) +{ + this->Makefile->StateSnapshot = + this->Makefile->GetState()->CreateVariableScopeSnapshot( + this->Makefile->StateSnapshot); +} + +cmMakefile::VariablePushPop::~VariablePushPop() +{ + this->Makefile->PopSnapshot(); +} + bool cmMakefile::HasCMP0054AlreadyBeenReported( cmListFileContext const& context) const { diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 27838b2..3866aca 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -270,7 +270,7 @@ public: */ void AddSubDirectory(const std::string& fullSrcDir, const std::string& fullBinDir, bool excludeFromAll, - bool immediate); + bool immediate, bool system); void Configure(); @@ -376,6 +376,20 @@ public: }; friend class PolicyPushPop; + /** Helper class to push and pop variables scopes automatically. */ + class VariablePushPop + { + public: + VariablePushPop(cmMakefile* m); + ~VariablePushPop(); + + VariablePushPop(VariablePushPop const&) = delete; + VariablePushPop& operator=(VariablePushPop const&) = delete; + + private: + cmMakefile* Makefile; + }; + /** * Determine if the given context, name pair has already been reported * in context of CMP0054. @@ -861,6 +875,11 @@ public: void PushScope(); void PopScope(); void RaiseScope(const std::string& var, const char* value); + void RaiseScope(const std::string& var, cmValue value) + { + this->RaiseScope(var, value.GetCStr()); + } + void RaiseScope(const std::vector<std::string>& variables); // push and pop loop scopes void PushLoopBlockBarrier(); @@ -924,6 +943,7 @@ public: }; void IssueMessage(MessageType t, std::string const& text) const; + Message::LogLevel GetCurrentLogLevel() const; /** Set whether or not to report a CMP0000 violation. */ void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; } diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 3849c6f..54f03b9 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -136,17 +136,11 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule( std::vector<std::string> depends; this->AppendLinkDepends(depends, linkLanguage); - // Build a list of compiler flags and linker flags. - std::string langFlags; - std::string linkFlags; - // Add language feature flags. + std::string langFlags; this->LocalGenerator->AddLanguageFlagsForLinking( langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); - // Add device-specific linker flags. - this->GetDeviceLinkFlags(linkFlags, linkLanguage); - // Construct a list of files associated with this executable that // may need to be cleaned. std::vector<std::string> exeCleanFiles; @@ -173,23 +167,32 @@ void cmMakefileExecutableTargetGenerator::WriteNvidiaDeviceExecutableRule( // Set path conversion for link script shells. this->LocalGenerator->SetLinkScriptShell(useLinkScript); - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineDeviceComputer> linkLineComputer( new cmLinkLineDeviceComputer( this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory())); linkLineComputer->SetForResponse(useResponseFileForLibs); linkLineComputer->SetRelink(relink); + // Create set of linking flags. + std::string linkFlags; + std::string ignored_; + this->LocalGenerator->GetDeviceLinkFlags( + *linkLineComputer, this->GetConfigName(), ignored_, linkFlags, ignored_, + ignored_, this->GeneratorTarget); + // Collect up flags to link in needed libraries. std::string linkLibs; - this->CreateLinkLibs(linkLineComputer.get(), linkLibs, - useResponseFileForLibs, depends); + this->CreateLinkLibs( + linkLineComputer.get(), linkLibs, useResponseFileForLibs, depends, + cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink); // Construct object file lists that may be needed to expand the // rule. std::string buildObjs; - this->CreateObjectLists(useLinkScript, false, useResponseFileForObjects, - buildObjs, depends, false); + this->CreateObjectLists( + useLinkScript, false, useResponseFileForObjects, buildObjs, depends, + false, cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink); cmRulePlaceholderExpander::RuleVariables vars; std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index f30ec27..45ef8c8 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -287,10 +287,6 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules( this->LocalGenerator->AddLanguageFlagsForLinking( langFlags, this->GeneratorTarget, linkLanguage, this->GetConfigName()); - // Create set of linking flags. - std::string linkFlags; - this->GetDeviceLinkFlags(linkFlags, linkLanguage); - // Clean files associated with this library. std::set<std::string> libCleanFiles; libCleanFiles.insert( @@ -315,22 +311,31 @@ void cmMakefileLibraryTargetGenerator::WriteNvidiaDeviceLibraryRules( // Collect up flags to link in needed libraries. std::string linkLibs; - std::unique_ptr<cmLinkLineComputer> linkLineComputer( + std::unique_ptr<cmLinkLineDeviceComputer> linkLineComputer( new cmLinkLineDeviceComputer( this->LocalGenerator, this->LocalGenerator->GetStateSnapshot().GetDirectory())); linkLineComputer->SetForResponse(useResponseFileForLibs); linkLineComputer->SetRelink(relink); - this->CreateLinkLibs(linkLineComputer.get(), linkLibs, - useResponseFileForLibs, depends); + // Create set of linking flags. + std::string linkFlags; + std::string ignored_; + this->LocalGenerator->GetDeviceLinkFlags( + *linkLineComputer, this->GetConfigName(), ignored_, linkFlags, ignored_, + ignored_, this->GeneratorTarget); + + this->CreateLinkLibs( + linkLineComputer.get(), linkLibs, useResponseFileForLibs, depends, + cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink); // Construct object file lists that may be needed to expand the // rule. std::string buildObjs; - this->CreateObjectLists(useLinkScript, false, // useArchiveRules - useResponseFileForObjects, buildObjs, depends, - false); + this->CreateObjectLists( + useLinkScript, false, // useArchiveRules + useResponseFileForObjects, buildObjs, depends, false, + cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink); std::string objectDir = this->GeneratorTarget->GetSupportDirectory(); objectDir = this->LocalGenerator->ConvertToOutputFormat( diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index aec6577..d19bbb9 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -21,6 +21,7 @@ #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" +#include "cmFileSet.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" @@ -46,6 +47,7 @@ #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" +#include "cmTarget.h" #include "cmValue.h" #include "cmake.h" @@ -107,7 +109,7 @@ std::unique_ptr<cmMakefileTargetGenerator> cmMakefileTargetGenerator::New( return result; } -std::string cmMakefileTargetGenerator::GetConfigName() +std::string cmMakefileTargetGenerator::GetConfigName() const { auto const& configNames = this->LocalGenerator->GetConfigNames(); assert(configNames.size() == 1); @@ -190,6 +192,16 @@ void cmMakefileTargetGenerator::CreateRuleFile() void cmMakefileTargetGenerator::WriteTargetBuildRules() { + this->GeneratorTarget->CheckCxxModuleStatus(this->GetConfigName()); + + if (this->GeneratorTarget->HaveCxx20ModuleSources()) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The \"", this->GeneratorTarget->GetName(), + "\" target contains C++ module sources which are not supported " + "by the generator")); + } + // -- Write the custom commands for this target // Evaluates generator expressions and expands prop_value @@ -302,6 +314,40 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() } } + std::map<std::string, std::string> file_set_map; + + auto const* tgt = this->GeneratorTarget->Target; + for (auto const& name : tgt->GetAllFileSetNames()) { + auto const* file_set = tgt->GetFileSet(name); + if (!file_set) { + this->Makefile->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("Target \"", tgt->GetName(), + "\" is tracked to have file set \"", name, + "\", but it was not found.")); + continue; + } + + auto fileEntries = file_set->CompileFileEntries(); + auto directoryEntries = file_set->CompileDirectoryEntries(); + auto directories = file_set->EvaluateDirectoryEntries( + directoryEntries, this->LocalGenerator, this->GetConfigName(), + this->GeneratorTarget); + + std::map<std::string, std::vector<std::string>> files; + for (auto const& entry : fileEntries) { + file_set->EvaluateFileEntry(directories, files, entry, + this->LocalGenerator, this->GetConfigName(), + this->GeneratorTarget); + } + + for (auto const& it : files) { + for (auto const& filename : it.second) { + file_set_map[filename] = file_set->GetType(); + } + } + } + std::vector<cmSourceFile const*> objectSources; this->GeneratorTarget->GetObjectSources(objectSources, this->GetConfigName()); @@ -314,6 +360,25 @@ void cmMakefileTargetGenerator::WriteTargetBuildRules() this->WriteObjectRuleFiles(*sf); } } + + for (cmSourceFile const* sf : objectSources) { + auto const& path = sf->GetFullPath(); + auto const it = file_set_map.find(path); + if (it != file_set_map.end()) { + auto const& file_set_type = it->second; + if (file_set_type == "CXX_MODULES"_s || + file_set_type == "CXX_MODULE_HEADER_UNITS"_s) { + if (sf->GetLanguage() != "CXX"_s) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Target \"", tgt->GetName(), "\" contains the source\n ", path, + "\nin a file set of type \"", file_set_type, + R"(" but the source is not classified as a "CXX" source.)")); + } + } + } + } } void cmMakefileTargetGenerator::WriteCommonCodeRules() @@ -977,8 +1042,10 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( lang == "OBJCXX")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); - if (cmNonempty(clauncher)) { - compilerLauncher = *clauncher; + std::string evaluatedClauncher = cmGeneratorExpression::Evaluate( + *clauncher, this->LocalGenerator, config); + if (!evaluatedClauncher.empty()) { + compilerLauncher = evaluatedClauncher; } } @@ -2080,7 +2147,7 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForLibraries( } std::string cmMakefileTargetGenerator::CreateResponseFile( - const char* name, std::string const& options, + const std::string& name, std::string const& options, std::vector<std::string>& makefile_depends) { // FIXME: Find a better way to determine the response file encoding, @@ -2126,7 +2193,8 @@ cmMakefileTargetGenerator::CreateLinkLineComputer( void cmMakefileTargetGenerator::CreateLinkLibs( cmLinkLineComputer* linkLineComputer, std::string& linkLibs, - bool useResponseFile, std::vector<std::string>& makefile_depends) + bool useResponseFile, std::vector<std::string>& makefile_depends, + ResponseFlagFor responseMode) { std::string frameworkPath; std::string linkPath; @@ -2139,20 +2207,13 @@ void cmMakefileTargetGenerator::CreateLinkLibs( if (useResponseFile && linkLibs.find_first_not_of(' ') != std::string::npos) { // Lookup the response file reference flag. - std::string responseFlagVar = - cmStrCat("CMAKE_", - this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), - "_RESPONSE_FILE_LINK_FLAG"); - std::string responseFlag; - if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) { - responseFlag = *p; - } else { - responseFlag = "@"; - } + std::string responseFlag = this->GetResponseFlag(responseMode); // Create this response file. + std::string responseFileName = + (responseMode == Link) ? "linkLibs.rsp" : "deviceLinkLibs.rsp"; std::string link_rsp = - this->CreateResponseFile("linklibs.rsp", linkLibs, makefile_depends); + this->CreateResponseFile(responseFileName, linkLibs, makefile_depends); // Reference the response file. linkLibs = cmStrCat(responseFlag, @@ -2164,7 +2225,7 @@ void cmMakefileTargetGenerator::CreateLinkLibs( void cmMakefileTargetGenerator::CreateObjectLists( bool useLinkScript, bool useArchiveRules, bool useResponseFile, std::string& buildObjs, std::vector<std::string>& makefile_depends, - bool useWatcomQuote) + bool useWatcomQuote, ResponseFlagFor responseMode) { std::string variableName; std::string variableNameExternal; @@ -2179,27 +2240,19 @@ void cmMakefileTargetGenerator::CreateObjectLists( this->WriteObjectsStrings(object_strings, responseFileLimit); // Lookup the response file reference flag. - std::string responseFlagVar = - cmStrCat("CMAKE_", - this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()), - "_RESPONSE_FILE_LINK_FLAG"); - std::string responseFlag; - if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) { - responseFlag = *p; - } else { - responseFlag = "@"; - } + std::string responseFlag = this->GetResponseFlag(responseMode); // Write a response file for each string. const char* sep = ""; for (unsigned int i = 0; i < object_strings.size(); ++i) { // Number the response files. - char rsp[32]; - snprintf(rsp, sizeof(rsp), "objects%u.rsp", i + 1); + std::string responseFileName = + (responseMode == Link) ? "objects" : "deviceObjects"; + responseFileName += std::to_string(i + 1); // Create this response file. - std::string objects_rsp = - this->CreateResponseFile(rsp, object_strings[i], makefile_depends); + std::string objects_rsp = this->CreateResponseFile( + responseFileName, object_strings[i], makefile_depends); // Separate from previous response file references. buildObjs += sep; @@ -2251,7 +2304,7 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags, } std::string name = cmStrCat("includes_", lang, ".rsp"); std::string arg = std::move(responseFlag) + - this->CreateResponseFile(name.c_str(), includeFlags, + this->CreateResponseFile(name, includeFlags, this->FlagFileDepends[lang]); this->LocalGenerator->AppendFlags(flags, arg); } else { @@ -2304,3 +2357,22 @@ void cmMakefileTargetGenerator::GenDefFile( fout << src->GetFullPath() << "\n"; } } + +std::string cmMakefileTargetGenerator::GetResponseFlag( + ResponseFlagFor mode) const +{ + std::string responseFlag = "@"; + std::string responseFlagVar; + + auto lang = this->GeneratorTarget->GetLinkerLanguage(this->GetConfigName()); + if (mode == cmMakefileTargetGenerator::ResponseFlagFor::Link) { + responseFlagVar = cmStrCat("CMAKE_", lang, "_RESPONSE_FILE_LINK_FLAG"); + } else if (mode == cmMakefileTargetGenerator::ResponseFlagFor::DeviceLink) { + responseFlagVar = "CMAKE_CUDA_RESPONSE_FILE_DEVICE_LINK_FLAG"; + } + + if (cmValue p = this->Makefile->GetDefinition(responseFlagVar)) { + responseFlag = *p; + } + return responseFlag; +} diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index cb804e0..dafa650 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -56,7 +56,7 @@ public: cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; } - std::string GetConfigName(); + std::string GetConfigName() const; protected: void GetDeviceLinkFlags(std::string& linkFlags, @@ -157,22 +157,31 @@ protected: /** Create a response file with the given set of options. Returns the relative path from the target build working directory to the response file name. */ - std::string CreateResponseFile(const char* name, std::string const& options, + std::string CreateResponseFile(const std::string& name, + std::string const& options, std::vector<std::string>& makefile_depends); bool CheckUseResponseFileForObjects(std::string const& l) const; bool CheckUseResponseFileForLibraries(std::string const& l) const; + enum ResponseFlagFor + { + Link, + DeviceLink + }; + /** Create list of flags for link libraries. */ void CreateLinkLibs(cmLinkLineComputer* linkLineComputer, std::string& linkLibs, bool useResponseFile, - std::vector<std::string>& makefile_depends); + std::vector<std::string>& makefile_depends, + ResponseFlagFor responseMode = ResponseFlagFor::Link); /** Create lists of object files for linking and cleaning. */ void CreateObjectLists(bool useLinkScript, bool useArchiveRules, bool useResponseFile, std::string& buildObjs, std::vector<std::string>& makefile_depends, - bool useWatcomQuote); + bool useWatcomQuote, + ResponseFlagFor responseMode = ResponseFlagFor::Link); /** Add commands for generate def files */ void GenDefFile(std::vector<std::string>& real_link_commands); @@ -180,6 +189,9 @@ protected: void AddIncludeFlags(std::string& flags, const std::string& lang, const std::string& config) override; + /** Return the response flag for the given configuration */ + std::string GetResponseFlag(ResponseFlagFor mode) const; + virtual void CloseFileStreams(); cmLocalUnixMakefileGenerator3* LocalGenerator; cmGlobalUnixMakefileGenerator3* GlobalGenerator; diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx index cd57600..fa29ec9 100644 --- a/Source/cmMessageCommand.cxx +++ b/Source/cmMessageCommand.cxx @@ -81,94 +81,83 @@ bool cmMessageCommand(std::vector<std::string> const& args, auto type = MessageType::MESSAGE; auto fatal = false; - auto level = cmake::LogLevel::LOG_UNDEFINED; + auto level = Message::LogLevel::LOG_UNDEFINED; auto checkingType = CheckingType::UNDEFINED; if (*i == "SEND_ERROR") { type = MessageType::FATAL_ERROR; - level = cmake::LogLevel::LOG_ERROR; + level = Message::LogLevel::LOG_ERROR; ++i; } else if (*i == "FATAL_ERROR") { fatal = true; type = MessageType::FATAL_ERROR; - level = cmake::LogLevel::LOG_ERROR; + level = Message::LogLevel::LOG_ERROR; ++i; } else if (*i == "WARNING") { type = MessageType::WARNING; - level = cmake::LogLevel::LOG_WARNING; + level = Message::LogLevel::LOG_WARNING; ++i; } else if (*i == "AUTHOR_WARNING") { if (mf.IsSet("CMAKE_SUPPRESS_DEVELOPER_ERRORS") && !mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_ERRORS")) { fatal = true; type = MessageType::AUTHOR_ERROR; - level = cmake::LogLevel::LOG_ERROR; + level = Message::LogLevel::LOG_ERROR; } else if (!mf.IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { type = MessageType::AUTHOR_WARNING; - level = cmake::LogLevel::LOG_WARNING; + level = Message::LogLevel::LOG_WARNING; } else { return true; } ++i; } else if (*i == "CHECK_START") { - level = cmake::LogLevel::LOG_STATUS; + level = Message::LogLevel::LOG_STATUS; checkingType = CheckingType::CHECK_START; ++i; } else if (*i == "CHECK_PASS") { - level = cmake::LogLevel::LOG_STATUS; + level = Message::LogLevel::LOG_STATUS; checkingType = CheckingType::CHECK_PASS; ++i; } else if (*i == "CHECK_FAIL") { - level = cmake::LogLevel::LOG_STATUS; + level = Message::LogLevel::LOG_STATUS; checkingType = CheckingType::CHECK_FAIL; ++i; } else if (*i == "STATUS") { - level = cmake::LogLevel::LOG_STATUS; + level = Message::LogLevel::LOG_STATUS; ++i; } else if (*i == "VERBOSE") { - level = cmake::LogLevel::LOG_VERBOSE; + level = Message::LogLevel::LOG_VERBOSE; ++i; } else if (*i == "DEBUG") { - level = cmake::LogLevel::LOG_DEBUG; + level = Message::LogLevel::LOG_DEBUG; ++i; } else if (*i == "TRACE") { - level = cmake::LogLevel::LOG_TRACE; + level = Message::LogLevel::LOG_TRACE; ++i; } else if (*i == "DEPRECATION") { if (mf.IsOn("CMAKE_ERROR_DEPRECATED")) { fatal = true; type = MessageType::DEPRECATION_ERROR; - level = cmake::LogLevel::LOG_ERROR; + level = Message::LogLevel::LOG_ERROR; } else if (!mf.IsSet("CMAKE_WARN_DEPRECATED") || mf.IsOn("CMAKE_WARN_DEPRECATED")) { type = MessageType::DEPRECATION_WARNING; - level = cmake::LogLevel::LOG_WARNING; + level = Message::LogLevel::LOG_WARNING; } else { return true; } ++i; } else if (*i == "NOTICE") { // `NOTICE` message type is going to be output to stderr - level = cmake::LogLevel::LOG_NOTICE; + level = Message::LogLevel::LOG_NOTICE; ++i; } else { // Messages w/o any type are `NOTICE`s - level = cmake::LogLevel::LOG_NOTICE; + level = Message::LogLevel::LOG_NOTICE; } assert("Message log level expected to be set" && - level != cmake::LogLevel::LOG_UNDEFINED); - - auto desiredLevel = mf.GetCMakeInstance()->GetLogLevel(); - assert("Expected a valid log level here" && - desiredLevel != cmake::LogLevel::LOG_UNDEFINED); - - // Command line option takes precedence over the cache variable - if (!mf.GetCMakeInstance()->WasLogLevelSetViaCLI()) { - const auto desiredLevelFromCache = - cmake::StringToLogLevel(mf.GetSafeDefinition("CMAKE_MESSAGE_LOG_LEVEL")); - if (desiredLevelFromCache != cmake::LogLevel::LOG_UNDEFINED) { - desiredLevel = desiredLevelFromCache; - } - } + level != Message::LogLevel::LOG_UNDEFINED); + + Message::LogLevel desiredLevel = mf.GetCurrentLogLevel(); if (desiredLevel < level) { // Suppress the message @@ -178,17 +167,17 @@ bool cmMessageCommand(std::vector<std::string> const& args, auto message = cmJoin(cmMakeRange(i, args.cend()), ""); switch (level) { - case cmake::LogLevel::LOG_ERROR: - case cmake::LogLevel::LOG_WARNING: + case Message::LogLevel::LOG_ERROR: + case Message::LogLevel::LOG_WARNING: // we've overridden the message type, above, so display it directly mf.GetMessenger()->DisplayMessage(type, message, mf.GetBacktrace()); break; - case cmake::LogLevel::LOG_NOTICE: + case Message::LogLevel::LOG_NOTICE: cmSystemTools::Message(IndentText(message, mf)); break; - case cmake::LogLevel::LOG_STATUS: + case Message::LogLevel::LOG_STATUS: switch (checkingType) { case CheckingType::CHECK_START: mf.DisplayStatus(IndentText(message, mf), -1); @@ -209,9 +198,9 @@ bool cmMessageCommand(std::vector<std::string> const& args, } break; - case cmake::LogLevel::LOG_VERBOSE: - case cmake::LogLevel::LOG_DEBUG: - case cmake::LogLevel::LOG_TRACE: + case Message::LogLevel::LOG_VERBOSE: + case Message::LogLevel::LOG_DEBUG: + case Message::LogLevel::LOG_TRACE: mf.DisplayStatus(IndentText(message, mf), -1); break; diff --git a/Source/cmMessageType.h b/Source/cmMessageType.h index 44de429..decb4b3 100644 --- a/Source/cmMessageType.h +++ b/Source/cmMessageType.h @@ -16,3 +16,19 @@ enum class MessageType DEPRECATION_ERROR, DEPRECATION_WARNING }; + +namespace Message { + +/** \brief Define log level constants. */ +enum class LogLevel +{ + LOG_UNDEFINED, + LOG_ERROR, + LOG_WARNING, + LOG_NOTICE, + LOG_STATUS, + LOG_VERBOSE, + LOG_DEBUG, + LOG_TRACE +}; +} diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index d4f1608..bda8a5f 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -537,7 +537,6 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd() // this target requires separable cuda compilation // now build the correct command depending on if the target is // an executable or a dynamic library. - std::string linkCmd; switch (this->GetGeneratorTarget()->GetType()) { case cmStateEnums::STATIC_LIBRARY: case cmStateEnums::SHARED_LIBRARY: @@ -1086,10 +1085,12 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( this->GetGeneratorTarget()->GetObjectSources(sources, config); cmLocalGenerator const* LocalGen = this->GetLocalGenerator(); for (const auto& source : sources) { + const std::string sourcePath = source->GetLanguage() == "Swift" + ? this->GetCompiledSourceNinjaPath(source) + : this->GetObjectFilePath(source, config); oss << " " - << LocalGen->ConvertToOutputFormat( - this->GetCompiledSourceNinjaPath(source), - cmOutputConverter::SHELL); + << LocalGen->ConvertToOutputFormat(sourcePath, + cmOutputConverter::SHELL); } return oss.str(); }(); @@ -1107,10 +1108,15 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( std::vector<cmSourceFile const*> sources; gt->GetObjectSources(sources, config); for (const auto& source : sources) { - linkBuild.Outputs.push_back( - this->ConvertToNinjaPath(this->GetObjectFilePath(source, config))); - linkBuild.ExplicitDeps.emplace_back( - this->GetCompiledSourceNinjaPath(source)); + if (source->GetLanguage() == "Swift") { + linkBuild.Outputs.push_back( + this->ConvertToNinjaPath(this->GetObjectFilePath(source, config))); + linkBuild.ExplicitDeps.emplace_back( + this->GetCompiledSourceNinjaPath(source)); + } else { + linkBuild.ExplicitDeps.emplace_back( + this->GetObjectFilePath(source, config)); + } } linkBuild.Outputs.push_back(vars["SWIFT_MODULE"]); } else { diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 3fac7f5..e4427f5 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -21,11 +21,17 @@ #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" +#include "cmExportBuildFileGenerator.h" +#include "cmExportSet.h" #include "cmFileSet.h" #include "cmGeneratedFileStream.h" #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalNinjaGenerator.h" +#include "cmInstallCxxModuleBmiGenerator.h" +#include "cmInstallExportGenerator.h" +#include "cmInstallFileSetGenerator.h" +#include "cmInstallGenerator.h" #include "cmLocalGenerator.h" #include "cmLocalNinjaGenerator.h" #include "cmMakefile.h" @@ -36,12 +42,12 @@ #include "cmRange.h" #include "cmRulePlaceholderExpander.h" #include "cmSourceFile.h" -#include "cmStandardLevelResolver.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" +#include "cmTargetExport.h" #include "cmValue.h" #include "cmake.h" @@ -153,17 +159,12 @@ std::string cmNinjaTargetGenerator::LanguageDyndepRule( bool cmNinjaTargetGenerator::NeedCxxModuleSupport( std::string const& lang, std::string const& config) const { - if (lang != "CXX") { + if (lang != "CXX"_s) { return false; } - if (!this->Makefile->IsOn("CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP")) { - return false; - } - cmGeneratorTarget const* tgt = this->GetGeneratorTarget(); - cmStandardLevelResolver standardResolver(this->Makefile); - bool const uses_cxx20 = - standardResolver.HaveStandardAvailable(tgt, "CXX", config, "cxx_std_20"); - return uses_cxx20 && this->GetGlobalGenerator()->CheckCxxModuleSupport(); + return this->GetGeneratorTarget()->HaveCxxModuleSupport(config) == + cmGeneratorTarget::Cxx20SupportLevel::Supported && + this->GetGlobalGenerator()->CheckCxxModuleSupport(); } bool cmNinjaTargetGenerator::NeedDyndep(std::string const& lang, @@ -255,51 +256,53 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( flags, genexInterpreter.Evaluate(pchOptions, COMPILE_OPTIONS)); } - if (this->NeedCxxModuleSupport(language, config)) { - auto const& path = source->GetFullPath(); - auto const* tgt = this->GeneratorTarget->Target; + auto const& path = source->GetFullPath(); + auto const* tgt = this->GeneratorTarget->Target; - std::string file_set_type; + std::string file_set_type; - for (auto const& name : tgt->GetAllFileSetNames()) { - auto const* file_set = tgt->GetFileSet(name); - if (!file_set) { - this->GetMakefile()->IssueMessage( - MessageType::INTERNAL_ERROR, - cmStrCat("Target `", tgt->GetName(), - "` is tracked to have file set `", name, - "`, but it was not found.")); - continue; - } + for (auto const& name : tgt->GetAllFileSetNames()) { + auto const* file_set = tgt->GetFileSet(name); + if (!file_set) { + this->GetMakefile()->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("Target \"", tgt->GetName(), + "\" is tracked to have file set \"", name, + "\", but it was not found.")); + continue; + } - auto fileEntries = file_set->CompileFileEntries(); - auto directoryEntries = file_set->CompileDirectoryEntries(); - auto directories = file_set->EvaluateDirectoryEntries( - directoryEntries, this->LocalGenerator, config, this->GeneratorTarget); + auto fileEntries = file_set->CompileFileEntries(); + auto directoryEntries = file_set->CompileDirectoryEntries(); + auto directories = file_set->EvaluateDirectoryEntries( + directoryEntries, this->LocalGenerator, config, this->GeneratorTarget); - std::map<std::string, std::vector<std::string>> files; - for (auto const& entry : fileEntries) { - file_set->EvaluateFileEntry(directories, files, entry, - this->LocalGenerator, config, - this->GeneratorTarget); - } + std::map<std::string, std::vector<std::string>> files; + for (auto const& entry : fileEntries) { + file_set->EvaluateFileEntry(directories, files, entry, + this->LocalGenerator, config, + this->GeneratorTarget); + } - for (auto const& it : files) { - for (auto const& filename : it.second) { - if (filename == path) { - file_set_type = file_set->GetType(); - break; - } + for (auto const& it : files) { + for (auto const& filename : it.second) { + if (filename == path) { + file_set_type = file_set->GetType(); + break; } } + } - if (!file_set_type.empty()) { - std::string source_type_var = cmStrCat( - "CMAKE_EXPERIMENTAL_CXX_MODULE_SOURCE_TYPE_FLAG_", file_set_type); - cmMakefile* mf = this->GetMakefile(); - if (cmValue source_type_flag = mf->GetDefinition(source_type_var)) { - this->LocalGenerator->AppendFlags(flags, *source_type_flag); - } + if (file_set_type == "CXX_MODULES"_s || + file_set_type == "CXX_MODULE_HEADER_UNITS"_s) { + if (source->GetLanguage() != "CXX"_s) { + this->GetMakefile()->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Target \"", tgt->GetName(), "\" contains the source\n ", path, + "\nin a file set of type \"", file_set_type, + R"(" but the source is not classified as a "CXX" source.)")); + continue; } } } @@ -909,8 +912,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, lang == "OBJCXX")) { std::string const clauncher_prop = cmStrCat(lang, "_COMPILER_LAUNCHER"); cmValue clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); - if (cmNonempty(clauncher)) { - compilerLauncher = *clauncher; + std::string evaluatedClauncher = cmGeneratorExpression::Evaluate( + *clauncher, this->LocalGenerator, config); + if (!evaluatedClauncher.empty()) { + compilerLauncher = evaluatedClauncher; } } @@ -1038,6 +1043,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( const std::string& config, const std::string& fileConfig, bool firstForConfig) { + this->GeneratorTarget->CheckCxxModuleStatus(config); + // Write comments. cmGlobalNinjaGenerator::WriteDivider(this->GetImplFileStream(fileConfig)); this->GetImplFileStream(fileConfig) @@ -1338,9 +1345,11 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( } } - this->ExportObjectCompileCommand( - language, sourceFilePath, objectDir, objectFileName, objectFileDir, - vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config); + if (firstForConfig) { + this->ExportObjectCompileCommand( + language, sourceFilePath, objectDir, objectFileName, objectFileDir, + vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config); + } objBuild.Outputs.push_back(objectFileName); if (firstForConfig) { @@ -1616,8 +1625,9 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, mod_dir = this->GeneratorTarget->GetFortranModuleDirectory( this->Makefile->GetHomeOutputDirectory()); } else if (lang == "CXX") { - mod_dir = - cmSystemTools::CollapseFullPath(this->GeneratorTarget->ObjectDirectory); + mod_dir = this->GetGlobalGenerator()->ExpandCFGIntDir( + cmSystemTools::CollapseFullPath(this->GeneratorTarget->ObjectDirectory), + config); } if (mod_dir.empty()) { mod_dir = this->Makefile->GetCurrentBinaryDirectory(); @@ -1654,6 +1664,215 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang, tdi_linked_target_dirs.append(l); } + cmTarget* tgt = this->GeneratorTarget->Target; + auto all_file_sets = tgt->GetAllFileSetNames(); + Json::Value& tdi_cxx_module_info = tdi["cxx-modules"] = Json::objectValue; + for (auto const& file_set_name : all_file_sets) { + auto* file_set = tgt->GetFileSet(file_set_name); + if (!file_set) { + this->GetMakefile()->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("Target \"", tgt->GetName(), + "\" is tracked to have file set \"", file_set_name, + "\", but it was not found.")); + continue; + } + auto fs_type = file_set->GetType(); + // We only care about C++ module sources here. + if (fs_type != "CXX_MODULES"_s) { + continue; + } + + auto fileEntries = file_set->CompileFileEntries(); + auto directoryEntries = file_set->CompileDirectoryEntries(); + + auto directories = file_set->EvaluateDirectoryEntries( + directoryEntries, this->GeneratorTarget->LocalGenerator, config, + this->GeneratorTarget); + std::map<std::string, std::vector<std::string>> files_per_dirs; + for (auto const& entry : fileEntries) { + file_set->EvaluateFileEntry(directories, files_per_dirs, entry, + this->GeneratorTarget->LocalGenerator, + config, this->GeneratorTarget); + } + + std::map<std::string, cmSourceFile const*> sf_map; + { + std::vector<cmSourceFile const*> objectSources; + this->GeneratorTarget->GetObjectSources(objectSources, config); + for (auto const* sf : objectSources) { + auto full_path = sf->GetFullPath(); + if (full_path.empty()) { + this->GetMakefile()->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("Target \"", tgt->GetName(), + "\" has a full path-less source file.")); + continue; + } + sf_map[full_path] = sf; + } + } + + Json::Value fs_dest = Json::nullValue; + for (auto const& ig : this->GetMakefile()->GetInstallGenerators()) { + if (auto const* fsg = + dynamic_cast<cmInstallFileSetGenerator const*>(ig.get())) { + if (fsg->GetTarget() == this->GeneratorTarget && + fsg->GetFileSet() == file_set) { + fs_dest = fsg->GetDestination(config); + continue; + } + } + } + + for (auto const& files_per_dir : files_per_dirs) { + for (auto const& file : files_per_dir.second) { + auto lookup = sf_map.find(file); + if (lookup == sf_map.end()) { + this->GetMakefile()->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("Target \"", tgt->GetName(), "\" has source file \"", + file, + R"(" which is not in any of its "FILE_SET BASE_DIRS".)")); + continue; + } + + auto const* sf = lookup->second; + + if (!sf) { + this->GetMakefile()->IssueMessage( + MessageType::INTERNAL_ERROR, + cmStrCat("Target \"", tgt->GetName(), "\" has source file \"", + file, "\" which has not been tracked properly.")); + continue; + } + + auto obj_path = this->GetObjectFilePath(sf, config); + Json::Value& tdi_module_info = tdi_cxx_module_info[obj_path] = + Json::objectValue; + + tdi_module_info["source"] = file; + tdi_module_info["relative-directory"] = files_per_dir.first; + tdi_module_info["name"] = file_set->GetName(); + tdi_module_info["type"] = file_set->GetType(); + tdi_module_info["visibility"] = + std::string(cmFileSetVisibilityToName(file_set->GetVisibility())); + tdi_module_info["destination"] = fs_dest; + } + } + } + + tdi["config"] = config; + + // Add information about the export sets that this target is a member of. + Json::Value& tdi_exports = tdi["exports"] = Json::arrayValue; + std::string export_name = this->GeneratorTarget->GetExportName(); + + cmInstallCxxModuleBmiGenerator const* bmi_gen = nullptr; + for (auto const& ig : this->GetMakefile()->GetInstallGenerators()) { + if (auto const* bmig = + dynamic_cast<cmInstallCxxModuleBmiGenerator const*>(ig.get())) { + if (bmig->GetTarget() == this->GeneratorTarget) { + bmi_gen = bmig; + continue; + } + } + } + if (bmi_gen) { + Json::Value tdi_bmi_info = Json::objectValue; + + tdi_bmi_info["permissions"] = bmi_gen->GetFilePermissions(); + tdi_bmi_info["destination"] = bmi_gen->GetDestination(config); + const char* msg_level = ""; + switch (bmi_gen->GetMessageLevel()) { + case cmInstallGenerator::MessageDefault: + break; + case cmInstallGenerator::MessageAlways: + msg_level = "MESSAGE_ALWAYS"; + break; + case cmInstallGenerator::MessageLazy: + msg_level = "MESSAGE_LAZY"; + break; + case cmInstallGenerator::MessageNever: + msg_level = "MESSAGE_NEVER"; + break; + } + tdi_bmi_info["message-level"] = msg_level; + tdi_bmi_info["script-location"] = bmi_gen->GetScriptLocation(config); + + tdi["bmi-installation"] = tdi_bmi_info; + } else { + tdi["bmi-installation"] = Json::nullValue; + } + + auto const& all_install_exports = + this->GetGlobalGenerator()->GetExportSets(); + for (auto const& exp : all_install_exports) { + // Ignore exports sets which are not for this target. + auto const& targets = exp.second.GetTargetExports(); + auto tgt_export = + std::find_if(targets.begin(), targets.end(), + [this](std::unique_ptr<cmTargetExport> const& te) { + return te->Target == this->GeneratorTarget; + }); + if (tgt_export == targets.end()) { + continue; + } + + auto const* installs = exp.second.GetInstallations(); + for (auto const* install : *installs) { + Json::Value tdi_export_info = Json::objectValue; + + auto const& ns = install->GetNamespace(); + auto const& dest = install->GetDestination(); + auto const& cxxm_dir = install->GetCxxModuleDirectory(); + auto const& export_prefix = install->GetTempDir(); + + tdi_export_info["namespace"] = ns; + tdi_export_info["export-name"] = export_name; + tdi_export_info["destination"] = dest; + tdi_export_info["cxx-module-info-dir"] = cxxm_dir; + tdi_export_info["export-prefix"] = export_prefix; + tdi_export_info["install"] = true; + + tdi_exports.append(tdi_export_info); + } + } + + auto const& all_build_exports = + this->GetMakefile()->GetExportBuildFileGenerators(); + for (auto const& exp : all_build_exports) { + std::vector<std::string> targets; + exp->GetTargets(targets); + + // Ignore exports sets which are not for this target. + auto const& name = this->GeneratorTarget->GetName(); + bool has_current_target = + std::any_of(targets.begin(), targets.end(), + [name](std::string const& tname) { return tname == name; }); + if (!has_current_target) { + continue; + } + + Json::Value tdi_export_info = Json::objectValue; + + auto const& ns = exp->GetNamespace(); + auto const& main_fn = exp->GetMainExportFileName(); + auto const& cxxm_dir = exp->GetCxxModuleDirectory(); + auto dest = cmsys::SystemTools::GetParentDirectory(main_fn); + auto const& export_prefix = + cmSystemTools::GetFilenamePath(exp->GetMainExportFileName()); + + tdi_export_info["namespace"] = ns; + tdi_export_info["export-name"] = export_name; + tdi_export_info["destination"] = dest; + tdi_export_info["cxx-module-info-dir"] = cxxm_dir; + tdi_export_info["export-prefix"] = export_prefix; + tdi_export_info["install"] = false; + + tdi_exports.append(tdi_export_info); + } + std::string const tdin = this->GetTargetDependInfoPath(lang, config); cmGeneratedFileStream tdif(tdin); tdif << tdi; diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index 6883535..299ab3a 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -527,6 +527,13 @@ bool cmOutputConverter::Shell_ArgumentNeedsQuotes(cm::string_view in, } } + /* UNC paths in MinGW Makefiles need quotes. */ + if ((flags & Shell_Flag_MinGWMake) && (flags & Shell_Flag_Make)) { + if (in.size() > 1 && in[0] == '\\' && in[1] == '\\') { + return true; + } + } + return false; } diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx index 95f3e7e..7e19566 100644 --- a/Source/cmParseArgumentsCommand.cxx +++ b/Source/cmParseArgumentsCommand.cxx @@ -10,6 +10,7 @@ #include <cm/string_view> #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" @@ -41,11 +42,18 @@ namespace { using options_map = std::map<std::string, bool>; using single_map = std::map<std::string, std::string>; -using multi_map = std::map<std::string, std::vector<std::string>>; -using options_set = std::set<std::string>; +using multi_map = + std::map<std::string, ArgumentParser::NonEmpty<std::vector<std::string>>>; +using options_set = std::set<cm::string_view>; struct UserArgumentParser : public cmArgumentParser<void> { + void BindKeywordsMissingValue(std::vector<cm::string_view>& ref) + { + this->cmArgumentParser<void>::BindKeywordMissingValue( + [&ref](Instance&, cm::string_view arg) { ref.emplace_back(arg); }); + } + template <typename T, typename H> void Bind(std::vector<std::string> const& names, std::map<std::string, T>& ref, H duplicateKey) @@ -208,9 +216,10 @@ bool cmParseArgumentsCommand(std::vector<std::string> const& args, } } - std::vector<std::string> keywordsMissingValues; + std::vector<cm::string_view> keywordsMissingValues; + parser.BindKeywordsMissingValue(keywordsMissingValues); - parser.Parse(list, &unparsed, &keywordsMissingValues); + parser.Parse(list, &unparsed); PassParsedArguments( prefix, status.GetMakefile(), options, singleValArgs, multiValArgs, diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index cb7402c..4643868 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -421,7 +421,17 @@ class cmMakefile; SELECT( \ POLICY, CMP0139, \ "The if() command supports path comparisons using PATH_EQUAL operator.", \ - 3, 24, 0, cmPolicies::WARN) + 3, 24, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0140, "The return() command checks its arguments.", 3, \ + 25, 0, cmPolicies::WARN) \ + SELECT( \ + POLICY, CMP0141, \ + "MSVC debug information format flags are selected by an abstraction.", 3, \ + 25, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0142, \ + "The Xcode generator does not append per-config suffixes to " \ + "library search paths.", \ + 3, 25, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ @@ -458,7 +468,8 @@ class cmMakefile; F(CMP0112) \ F(CMP0113) \ F(CMP0119) \ - F(CMP0131) + F(CMP0131) \ + F(CMP0142) /** \class cmPolicies * \brief Handles changes in CMake behavior and policies diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 40f3ab5..96649ab 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1792,13 +1792,16 @@ void cmQtAutoGenInitializer::AddGeneratedSource(ConfigString const& filename, // XXX(xcode-per-cfg-src): Drop the Xcode-specific part of the condition // when the Xcode generator supports per-config sources. if (!this->MultiConfig || this->GlobalGen->IsXcode()) { - this->AddGeneratedSource(filename.Default, genVars, prepend); + cmSourceFile* sf = + this->AddGeneratedSource(filename.Default, genVars, prepend); + handleSkipPch(sf); return; } for (auto const& cfg : this->ConfigsList) { std::string const& filenameCfg = filename.Config.at(cfg); // Register source at makefile - this->RegisterGeneratedSource(filenameCfg); + cmSourceFile* sf = this->RegisterGeneratedSource(filenameCfg); + handleSkipPch(sf); // Add source file to target for this configuration. this->GenTarget->AddSource( cmStrCat("$<$<CONFIG:"_s, cfg, ">:"_s, filenameCfg, ">"_s), prepend); @@ -1847,8 +1850,7 @@ void cmQtAutoGenInitializer::AddToSourceGroup(std::string const& fileName, void cmQtAutoGenInitializer::AddCleanFile(std::string const& fileName) { - this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", fileName, - false); + this->GenTarget->Target->AppendProperty("ADDITIONAL_CLEAN_FILES", fileName); } void cmQtAutoGenInitializer::ConfigFileNames(ConfigString& configString, @@ -2159,3 +2161,18 @@ bool cmQtAutoGenInitializer::GetQtExecutable(GenVarsT& genVars, return true; } + +void cmQtAutoGenInitializer::handleSkipPch(cmSourceFile* sf) +{ + bool skipPch = true; + for (auto const& pair : this->AutogenTarget.Sources) { + if (!pair.first->GetIsGenerated() && + !pair.first->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + skipPch = false; + } + } + + if (skipPch) { + sf->SetProperty("SKIP_PRECOMPILE_HEADERS", "ON"); + } +} diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h index 33749ba..6d5261a 100644 --- a/Source/cmQtAutoGenInitializer.h +++ b/Source/cmQtAutoGenInitializer.h @@ -154,6 +154,8 @@ private: bool GetQtExecutable(GenVarsT& genVars, const std::string& executable, bool ignoreMissingTarget) const; + void handleSkipPch(cmSourceFile* sf); + cmQtAutoGenGlobalInitializer* GlobalInitializer = nullptr; cmGeneratorTarget* GenTarget = nullptr; cmGlobalGenerator* GlobalGen = nullptr; diff --git a/Source/cmReturnCommand.cxx b/Source/cmReturnCommand.cxx index 5905669..765b772 100644 --- a/Source/cmReturnCommand.cxx +++ b/Source/cmReturnCommand.cxx @@ -2,12 +2,52 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmReturnCommand.h" +#include <cm/string_view> +#include <cmext/string_view> + #include "cmExecutionStatus.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmPolicies.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" // cmReturnCommand -bool cmReturnCommand(std::vector<std::string> const&, +bool cmReturnCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { - status.SetReturnInvoked(); + if (!args.empty()) { + switch (status.GetMakefile().GetPolicyStatus(cmPolicies::CMP0140)) { + case cmPolicies::WARN: + status.GetMakefile().IssueMessage( + MessageType::AUTHOR_WARNING, + cmStrCat( + cmPolicies::GetPolicyWarning(cmPolicies::CMP0140), '\n', + "return() checks its arguments when the policy is set to NEW. " + "Since the policy is not set the OLD behavior will be used so " + "the arguments will be ignored.")); + CM_FALLTHROUGH; + case cmPolicies::OLD: + return true; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + status.GetMakefile().IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat('\n', cmPolicies::GetPolicyWarning(cmPolicies::CMP0140))); + cmSystemTools::SetFatalErrorOccurred(); + return false; + default: + break; + } + if (args[0] != "PROPAGATE"_s) { + status.SetError( + cmStrCat("called with unsupported argument \"", args[0], '"')); + cmSystemTools::SetFatalErrorOccurred(); + return false; + } + status.SetReturnInvoked({ args.begin() + 1, args.end() }); + } else { + status.SetReturnInvoked(); + } return true; } diff --git a/Source/cmScanDepFormat.cxx b/Source/cmScanDepFormat.cxx index 82a374a..ec53af5 100644 --- a/Source/cmScanDepFormat.cxx +++ b/Source/cmScanDepFormat.cxx @@ -5,6 +5,7 @@ #include <cctype> #include <cstdio> +#include <iostream> #include <utility> #include <cm/optional> @@ -188,6 +189,19 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, return false; } + if (provide.isMember("is-interface")) { + Json::Value const& is_interface = provide["is-interface"]; + if (!is_interface.isBool()) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": is-interface is not a boolean")); + return false; + } + provide_info.IsInterface = is_interface.asBool(); + } else { + provide_info.IsInterface = true; + } + info->Provides.push_back(provide_info); } } @@ -267,6 +281,27 @@ bool cmScanDepFormat_P1689_Parse(std::string const& arg_pp, info->Requires.push_back(require_info); } } + + // MSVC 17.3 toolchain bug. Remove when 17.4 is available. + if (rule.isMember("is-interface")) { + std::cerr + << "warning: acknowledging an VS 17.3 toolchain bug; accepting " + "until a new release which fixes it is available" + << std::endl; + + Json::Value const& is_interface_json = rule["is-interface"]; + if (!is_interface_json.isBool()) { + cmSystemTools::Error( + cmStrCat("-E cmake_ninja_dyndep failed to parse ", arg_pp, + ": is-interface is not a boolean")); + return false; + } + bool is_interface = is_interface_json.asBool(); + + for (auto& provide : info->Provides) { + provide.IsInterface = is_interface; + } + } } } @@ -308,6 +343,8 @@ bool cmScanDepFormat_P1689_Write(std::string const& path, provide_obj["source-path"] = EncodeFilename(provide.SourcePath); } + provide_obj["is-interface"] = provide.IsInterface; + provides.append(provide_obj); } diff --git a/Source/cmScanDepFormat.h b/Source/cmScanDepFormat.h index dae28d9..dc55bf1 100644 --- a/Source/cmScanDepFormat.h +++ b/Source/cmScanDepFormat.h @@ -18,6 +18,11 @@ struct cmSourceReqInfo std::string SourcePath; std::string CompiledModulePath; bool UseSourcePath = false; + + // Provides-only fields. + bool IsInterface = true; + + // Requires-only fields. LookupMethod Method = LookupMethod::ByName; }; diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx index 166ee56..32f9bec 100644 --- a/Source/cmScriptGenerator.cxx +++ b/Source/cmScriptGenerator.cxx @@ -133,7 +133,7 @@ void cmScriptGenerator::GenerateScriptActionsOnce(std::ostream& os, std::string config_test = this->CreateConfigTest(this->Configurations); os << indent << "if(" << config_test << ")\n"; this->GenerateScriptActions(os, indent.Next()); - os << indent << "endif(" << config_test << ")\n"; + os << indent << "endif()\n"; } } diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index db10cd4..521cf63 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -9,6 +9,7 @@ #include "cmExecutionStatus.h" #include "cmGlobalGenerator.h" #include "cmInstalledFile.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -561,7 +562,8 @@ bool HandleTarget(cmTarget* target, cmMakefile& makefile, { // Set or append the property. if (appendMode) { - target->AppendProperty(propertyName, propertyValue, appendAsString); + target->AppendProperty(propertyName, propertyValue, + makefile.GetBacktrace(), appendAsString); } else { if (remove) { target->SetProperty(propertyName, nullptr); diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 785f356..d2eac0c 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -18,6 +18,7 @@ #include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" @@ -378,25 +379,29 @@ std::unordered_map<std::string, StandardLevelComputer> "C", std::vector<int>{ 90, 99, 11, 17, 23 }, std::vector<std::string>{ "90", "99", "11", "17", "23" } } }, { "CXX", - StandardLevelComputer{ - "CXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 }, - std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } }, + StandardLevelComputer{ "CXX", + std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 }, + std::vector<std::string>{ "98", "11", "14", "17", + "20", "23", "26" } } }, { "CUDA", - StandardLevelComputer{ - "CUDA", std::vector<int>{ 03, 11, 14, 17, 20, 23 }, - std::vector<std::string>{ "03", "11", "14", "17", "20", "23" } } }, + StandardLevelComputer{ "CUDA", + std::vector<int>{ 03, 11, 14, 17, 20, 23, 26 }, + std::vector<std::string>{ "03", "11", "14", "17", + "20", "23", "26" } } }, { "OBJC", StandardLevelComputer{ "OBJC", std::vector<int>{ 90, 99, 11, 17, 23 }, std::vector<std::string>{ "90", "99", "11", "17", "23" } } }, { "OBJCXX", - StandardLevelComputer{ - "OBJCXX", std::vector<int>{ 98, 11, 14, 17, 20, 23 }, - std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } }, + StandardLevelComputer{ "OBJCXX", + std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 }, + std::vector<std::string>{ "98", "11", "14", "17", + "20", "23", "26" } } }, { "HIP", - StandardLevelComputer{ - "HIP", std::vector<int>{ 98, 11, 14, 17, 20, 23 }, - std::vector<std::string>{ "98", "11", "14", "17", "20", "23" } } } + StandardLevelComputer{ "HIP", + std::vector<int>{ 98, 11, 14, 17, 20, 23, 26 }, + std::vector<std::string>{ "98", "11", "14", "17", + "20", "23", "26" } } } }; } @@ -416,7 +421,8 @@ bool cmStandardLevelResolver::AddRequiredTargetFeature( cmTarget* target, const std::string& feature, std::string* error) const { if (cmGeneratorExpression::Find(feature) != std::string::npos) { - target->AppendProperty("COMPILE_FEATURES", feature); + target->AppendProperty("COMPILE_FEATURES", feature, + this->Makefile->GetBacktrace()); return true; } @@ -426,7 +432,8 @@ bool cmStandardLevelResolver::AddRequiredTargetFeature( return false; } - target->AppendProperty("COMPILE_FEATURES", feature); + target->AppendProperty("COMPILE_FEATURES", feature, + this->Makefile->GetBacktrace()); // FIXME: Add a policy to avoid updating the <LANG>_STANDARD target // property due to COMPILE_FEATURES. The language standard selection diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx index f73df8f..c51650a 100644 --- a/Source/cmStateSnapshot.cxx +++ b/Source/cmStateSnapshot.cxx @@ -317,6 +317,25 @@ void cmStateSnapshot::SetDefaultDefinitions() this->SetDefinition("CMAKE_HOST_SOLARIS", "1"); #endif +#if defined(__OpenBSD__) + this->SetDefinition("BSD", "OpenBSD"); + this->SetDefinition("CMAKE_HOST_BSD", "OpenBSD"); +#elif defined(__FreeBSD__) + this->SetDefinition("BSD", "FreeBSD"); + this->SetDefinition("CMAKE_HOST_BSD", "FreeBSD"); +#elif defined(__NetBSD__) + this->SetDefinition("BSD", "NetBSD"); + this->SetDefinition("CMAKE_HOST_BSD", "NetBSD"); +#elif defined(__DragonFly__) + this->SetDefinition("BSD", "DragonFlyBSD"); + this->SetDefinition("CMAKE_HOST_BSD", "DragonFlyBSD"); +#endif + +#if defined(__linux__) + this->SetDefinition("LINUX", "1"); + this->SetDefinition("CMAKE_HOST_LINUX", "1"); +#endif + this->SetDefinition("CMAKE_MAJOR_VERSION", std::to_string(cmVersion::GetMajorVersion())); this->SetDefinition("CMAKE_MINOR_VERSION", diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index c3ee695..c12d1fe 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -143,7 +143,8 @@ bool HandleHexCommand(std::vector<std::string> const& args, std::string::size_type hexIndex = 0; for (auto const& c : instr) { - sprintf(&output[hexIndex], "%.2x", static_cast<unsigned char>(c) & 0xFF); + snprintf(&output[hexIndex], 3, "%.2x", + static_cast<unsigned char>(c) & 0xFF); hexIndex += 2; } @@ -1013,7 +1014,7 @@ int ParseIndex( Json::ArrayIndex index = static_cast<Json::ArrayIndex>(lindex); if (index >= max) { cmAlphaNum sizeStr{ max }; - throw json_error({ "expected an index less then "_s, sizeStr.View(), + throw json_error({ "expected an index less than "_s, sizeStr.View(), " got '"_s, str, "'"_s }, progress); } diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx index 2477d7a..47082f1 100644 --- a/Source/cmSubdirCommand.cxx +++ b/Source/cmSubdirCommand.cxx @@ -32,7 +32,7 @@ bool cmSubdirCommand(std::vector<std::string> const& args, std::string srcPath = mf.GetCurrentSourceDirectory() + "/" + i; if (cmSystemTools::FileIsDirectory(srcPath)) { std::string binPath = mf.GetCurrentBinaryDirectory() + "/" + i; - mf.AddSubDirectory(srcPath, binPath, excludeFromAll, false); + mf.AddSubDirectory(srcPath, binPath, excludeFromAll, false, false); } // otherwise it is a full path else if (cmSystemTools::FileIsDirectory(i)) { @@ -40,7 +40,7 @@ bool cmSubdirCommand(std::vector<std::string> const& args, // element from the source path and use that std::string binPath = mf.GetCurrentBinaryDirectory() + "/" + cmSystemTools::GetFilenameName(i); - mf.AddSubDirectory(i, binPath, excludeFromAll, false); + mf.AddSubDirectory(i, binPath, excludeFromAll, false, false); } else { status.SetError(cmStrCat("Incorrect SUBDIRS command. Directory: ", i, " does not exist.")); diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index f077801..ee74908 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -11,11 +11,17 @@ // NOLINTNEXTLINE(bugprone-reserved-identifier) # define _XOPEN_SOURCE 700 #endif +#if defined(__APPLE__) +// Restore Darwin APIs removed by _POSIX_C_SOURCE. +// NOLINTNEXTLINE(bugprone-reserved-identifier) +# define _DARWIN_C_SOURCE +#endif #include "cmSystemTools.h" #include <cm/optional> #include <cmext/algorithm> +#include <cmext/string_view> #include <cm3p/uv.h> @@ -87,7 +93,6 @@ # include <unistd.h> # include <sys/time.h> -# include <sys/types.h> #endif #if defined(_WIN32) && \ @@ -1000,6 +1005,93 @@ void cmSystemTools::InitializeLibUV() #endif } +#if defined(_WIN32) +# include <random> + +# include <wctype.h> +# ifdef _MSC_VER +using mode_t = cmSystemTools::SystemTools::mode_t; +# endif +#else +# include <sys/stat.h> +#endif + +inline int Mkdir(const char* dir, const mode_t* mode) +{ +#if defined(_WIN32) + int ret = _wmkdir(cmSystemTools::ConvertToWindowsExtendedPath(dir).c_str()); + if (ret == 0 && mode) + cmSystemTools::SystemTools::SetPermissions(dir, *mode); + return ret; +#else + return mkdir(dir, mode ? *mode : 0777); +#endif +} + +cmsys::Status cmSystemTools::MakeTempDirectory(std::string& path, + const mode_t* mode) +{ + if (path.empty()) { + return cmsys::Status::POSIX(EINVAL); + } + return cmSystemTools::MakeTempDirectory(&path.front(), mode); +} + +cmsys::Status cmSystemTools::MakeTempDirectory(char* path, const mode_t* mode) +{ + if (!path) { + return cmsys::Status::POSIX(EINVAL); + } + + // verify that path ends with "XXXXXX" + const auto l = std::strlen(path); + if (!cmHasLiteralSuffix(cm::string_view{ path, l }, "XXXXXX")) { + return cmsys::Status::POSIX(EINVAL); + } + + // create parent directories + auto* sep = path; + while ((sep = strchr(sep, '/'))) { + // all underlying functions use C strings, + // so temporarily end the string here + *sep = '\0'; + Mkdir(path, mode); + + *sep = '/'; + ++sep; + } + +#ifdef _WIN32 + const int nchars = 36; + const char chars[nchars + 1] = "abcdefghijklmnopqrstuvwxyz0123456789"; + + std::random_device rd; + std::mt19937 rg{ rd() }; + std::uniform_int_distribution<int> dist{ 0, nchars - 1 }; + + for (auto tries = 100; tries; --tries) { + for (auto n = l - 6; n < l; ++n) { + path[n] = chars[dist(rg)]; + } + if (Mkdir(path, mode) == 0) { + return cmsys::Status::Success(); + } else if (errno != EEXIST) { + return cmsys::Status::POSIX_errno(); + } + } + return cmsys::Status::POSIX(EAGAIN); +#else + if (mkdtemp(path)) { + if (mode) { + chmod(path, *mode); + } + } else { + return cmsys::Status::POSIX_errno(); + } + return cmsys::Status::Success(); +#endif +} + #ifdef _WIN32 namespace { bool cmMoveFile(std::wstring const& oldname, std::wstring const& newname, @@ -1256,7 +1348,7 @@ std::string cmSystemTools::ComputeCertificateThumbprint( certContext, CERT_HASH_PROP_ID, hashData, &hashLength)) { for (DWORD i = 0; i < hashLength; i++) { // Convert each byte to hexadecimal - sprintf(pHashPrint, "%02X", hashData[i]); + snprintf(pHashPrint, 3, "%02X", hashData[i]); pHashPrint += 2; } *pHashPrint = '\0'; @@ -1539,8 +1631,7 @@ std::string cmSystemTools::RelativeIfUnder(std::string const& top, bool cmSystemTools::UnsetEnv(const char* value) { # if !defined(HAVE_UNSETENV) - std::string var = cmStrCat(value, '='); - return cmSystemTools::PutEnv(var); + return cmSystemTools::UnPutEnv(value); # else unsetenv(value); return true; @@ -1551,9 +1642,18 @@ std::vector<std::string> cmSystemTools::GetEnvironmentVariables() { std::vector<std::string> env; int cc; +# ifdef _WIN32 + // if program starts with main, _wenviron is initially NULL, call to + // _wgetenv and create wide-character string environment + _wgetenv(L""); + for (cc = 0; _wenviron[cc]; ++cc) { + env.emplace_back(cmsys::Encoding::ToNarrow(_wenviron[cc])); + } +# else for (cc = 0; environ[cc]; ++cc) { env.emplace_back(environ[cc]); } +# endif return env; } @@ -1564,6 +1664,144 @@ void cmSystemTools::AppendEnv(std::vector<std::string> const& env) } } +void cmSystemTools::EnvDiff::AppendEnv(std::vector<std::string> const& env) +{ + for (std::string const& eit : env) { + this->PutEnv(eit); + } +} + +void cmSystemTools::EnvDiff::PutEnv(const std::string& env) +{ + auto const eq_loc = env.find('='); + if (eq_loc != std::string::npos) { + std::string name = env.substr(0, eq_loc); + diff[name] = env.substr(eq_loc + 1); + } else { + this->UnPutEnv(env); + } +} + +void cmSystemTools::EnvDiff::UnPutEnv(const std::string& env) +{ + diff[env] = {}; +} + +bool cmSystemTools::EnvDiff::ParseOperation(const std::string& envmod) +{ + char path_sep = GetSystemPathlistSeparator(); + + auto apply_diff = [this](const std::string& name, + std::function<void(std::string&)> const& apply) { + cm::optional<std::string> old_value = diff[name]; + std::string output; + if (old_value) { + output = *old_value; + } else { + const char* curval = cmSystemTools::GetEnv(name); + if (curval) { + output = curval; + } + } + apply(output); + diff[name] = output; + }; + + // Split on `=` + auto const eq_loc = envmod.find_first_of('='); + if (eq_loc == std::string::npos) { + cmSystemTools::Error(cmStrCat( + "Error: Missing `=` after the variable name in: ", envmod, '\n')); + return false; + } + + auto const name = envmod.substr(0, eq_loc); + + // Split value on `:` + auto const op_value_start = eq_loc + 1; + auto const colon_loc = envmod.find_first_of(':', op_value_start); + if (colon_loc == std::string::npos) { + cmSystemTools::Error( + cmStrCat("Error: Missing `:` after the operation in: ", envmod, '\n')); + return false; + } + auto const op = envmod.substr(op_value_start, colon_loc - op_value_start); + + auto const value_start = colon_loc + 1; + auto const value = envmod.substr(value_start); + + // Determine what to do with the operation. + if (op == "reset"_s) { + auto entry = diff.find(name); + if (entry != diff.end()) { + diff.erase(entry); + } + } else if (op == "set"_s) { + diff[name] = value; + } else if (op == "unset"_s) { + diff[name] = {}; + } else if (op == "string_append"_s) { + apply_diff(name, [&value](std::string& output) { output += value; }); + } else if (op == "string_prepend"_s) { + apply_diff(name, + [&value](std::string& output) { output.insert(0, value); }); + } else if (op == "path_list_append"_s) { + apply_diff(name, [&value, path_sep](std::string& output) { + if (!output.empty()) { + output += path_sep; + } + output += value; + }); + } else if (op == "path_list_prepend"_s) { + apply_diff(name, [&value, path_sep](std::string& output) { + if (!output.empty()) { + output.insert(output.begin(), path_sep); + } + output.insert(0, value); + }); + } else if (op == "cmake_list_append"_s) { + apply_diff(name, [&value](std::string& output) { + if (!output.empty()) { + output += ';'; + } + output += value; + }); + } else if (op == "cmake_list_prepend"_s) { + apply_diff(name, [&value](std::string& output) { + if (!output.empty()) { + output.insert(output.begin(), ';'); + } + output.insert(0, value); + }); + } else { + cmSystemTools::Error(cmStrCat( + "Error: Unrecognized environment manipulation argument: ", op, '\n')); + return false; + } + + return true; +} + +void cmSystemTools::EnvDiff::ApplyToCurrentEnv(std::ostringstream* measurement) +{ + for (auto const& env_apply : diff) { + if (env_apply.second) { + auto const env_update = + cmStrCat(env_apply.first, '=', *env_apply.second); + cmSystemTools::PutEnv(env_update); + if (measurement) { + *measurement << env_update << std::endl; + } + } else { + cmSystemTools::UnsetEnv(env_apply.first.c_str()); + if (measurement) { + // Signify that this variable is being actively unset + *measurement << '#' << env_apply.first << "=\n"; + } + } + } +} + cmSystemTools::SaveRestoreEnvironment::SaveRestoreEnvironment() { this->Env = cmSystemTools::GetEnvironmentVariables(); @@ -3352,8 +3590,19 @@ std::string cmSystemTools::EncodeURL(std::string const& in, bool escapeSlashes) } cmsys::Status cmSystemTools::CreateSymlink(std::string const& origName, - std::string const& newName, - std::string* errorMessage) + std::string const& newName) +{ + cmsys::Status status = + cmSystemTools::CreateSymlinkQuietly(origName, newName); + if (!status) { + cmSystemTools::Error(cmStrCat("failed to create symbolic link '", newName, + "': ", status.GetString())); + } + return status; +} + +cmsys::Status cmSystemTools::CreateSymlinkQuietly(std::string const& origName, + std::string const& newName) { uv_fs_t req; int flags = 0; @@ -3373,20 +3622,23 @@ cmsys::Status cmSystemTools::CreateSymlink(std::string const& origName, #else status = cmsys::Status::POSIX(-err); #endif - std::string e = cmStrCat("failed to create symbolic link '", newName, - "': ", status.GetString()); - if (errorMessage) { - *errorMessage = std::move(e); - } else { - cmSystemTools::Error(e); - } } return status; } cmsys::Status cmSystemTools::CreateLink(std::string const& origName, - std::string const& newName, - std::string* errorMessage) + std::string const& newName) +{ + cmsys::Status status = cmSystemTools::CreateLinkQuietly(origName, newName); + if (!status) { + cmSystemTools::Error( + cmStrCat("failed to create link '", newName, "': ", status.GetString())); + } + return status; +} + +cmsys::Status cmSystemTools::CreateLinkQuietly(std::string const& origName, + std::string const& newName) { uv_fs_t req; int err = @@ -3400,13 +3652,6 @@ cmsys::Status cmSystemTools::CreateLink(std::string const& origName, #else status = cmsys::Status::POSIX(-err); #endif - std::string e = - cmStrCat("failed to create link '", newName, "': ", status.GetString()); - if (errorMessage) { - *errorMessage = std::move(e); - } else { - cmSystemTools::Error(e); - } } return status; } diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index ec650f7..87b354c 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -4,11 +4,18 @@ #include "cmConfigure.h" // IWYU pragma: keep +#if !defined(_WIN32) +# include <sys/types.h> +#endif + #include <cstddef> #include <functional> +#include <map> +#include <sstream> #include <string> #include <vector> +#include <cm/optional> #include <cm/string_view> #include "cmsys/Process.h" @@ -148,6 +155,27 @@ public: Failure, }; +#if defined(_MSC_VER) + /** Visual C++ does not define mode_t. */ + using mode_t = unsigned short; +#endif + + /** + * Make a new temporary directory. The path must end in "XXXXXX", and will + * be modified to reflect the name of the directory created. This function + * is similar to POSIX mkdtemp (and is implemented using the same where that + * function is available). + * + * This function can make a full path even if none of the directories existed + * prior to calling this function. + * + * Note that this function may modify \p path even if it does not succeed. + */ + static cmsys::Status MakeTempDirectory(char* path, + const mode_t* mode = nullptr); + static cmsys::Status MakeTempDirectory(std::string& path, + const mode_t* mode = nullptr); + /** Copy a file. */ static bool CopySingleFile(const std::string& oldname, const std::string& newname); @@ -377,6 +405,42 @@ public: /** Append multiple variables to the current environment. */ static void AppendEnv(std::vector<std::string> const& env); + /** + * Helper class to represent an environment diff directly. This is to avoid + * repeated in-place environment modification (i.e. via setenv/putenv), which + * could be slow. + */ + class EnvDiff + { + public: + /** Append multiple variables to the current environment diff */ + void AppendEnv(std::vector<std::string> const& env); + + /** + * Add a single variable (or remove if no = sign) to the current + * environment diff. + */ + void PutEnv(const std::string& env); + + /** Remove a single variable from the current environment diff. */ + void UnPutEnv(const std::string& env); + + /** + * Apply an ENVIRONMENT_MODIFICATION operation to this diff. Returns + * false and issues an error on parse failure. + */ + bool ParseOperation(const std::string& envmod); + + /** + * Apply this diff to the actual environment, optionally writing out the + * modifications to a CTest-compatible measurement stream. + */ + void ApplyToCurrentEnv(std::ostringstream* measurement = nullptr); + + private: + std::map<std::string, cm::optional<std::string>> diff; + }; + /** Helper class to save and restore the environment. Instantiate this class as an automatic variable on the stack. Its constructor saves a copy of the current @@ -531,14 +595,16 @@ public: /** Create a symbolic link if the platform supports it. Returns whether creation succeeded. */ static cmsys::Status CreateSymlink(std::string const& origName, - std::string const& newName, - std::string* errorMessage = nullptr); + std::string const& newName); + static cmsys::Status CreateSymlinkQuietly(std::string const& origName, + std::string const& newName); /** Create a hard link if the platform supports it. Returns whether creation succeeded. */ static cmsys::Status CreateLink(std::string const& origName, - std::string const& newName, - std::string* errorMessage = nullptr); + std::string const& newName); + static cmsys::Status CreateLinkQuietly(std::string const& origName, + std::string const& newName); /** Get the system name. */ static cm::string_view GetSystemName(); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index cbe5d7d..874195b 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -272,6 +272,8 @@ public: cmListFileBacktrace Backtrace; FileSetType HeadersFileSets; + FileSetType CxxModulesFileSets; + FileSetType CxxModuleHeadersFileSets; cmTargetInternals(); @@ -293,6 +295,12 @@ public: cm::string_view fileSetType) const; cmValue GetFileSetPaths(cmTarget const* self, std::string const& fileSetName, cm::string_view fileSetType) const; + + cmListFileBacktrace GetBacktrace( + cm::optional<cmListFileBacktrace> const& bt) const + { + return bt ? *bt : this->Makefile->GetBacktrace(); + } }; cmTargetInternals::cmTargetInternals() @@ -301,6 +309,19 @@ cmTargetInternals::cmTargetInternals() "The default header set"_s, "Header set"_s, FileSetEntries("HEADER_SETS"_s), FileSetEntries("INTERFACE_HEADER_SETS"_s)) + , CxxModulesFileSets("CXX_MODULES"_s, "CXX_MODULE_DIRS"_s, + "CXX_MODULE_SET"_s, "CXX_MODULE_DIRS_"_s, + "CXX_MODULE_SET_"_s, "C++ module"_s, + "The default C++ module set"_s, "C++ module set"_s, + FileSetEntries("CXX_MODULE_SETS"_s), + FileSetEntries("INTERFACE_CXX_MODULE_SETS"_s)) + , CxxModuleHeadersFileSets( + "CXX_MODULE_HEADER_UNITS"_s, "CXX_MODULE_HEADER_UNIT_DIRS"_s, + "CXX_MODULE_HEADER_UNIT_SET"_s, "CXX_MODULE_HEADER_UNIT_DIRS_"_s, + "CXX_MODULE_HEADER_UNIT_SET_"_s, "C++ module header"_s, + "The default C++ module header set"_s, "C++ module header set"_s, + FileSetEntries("CXX_MODULE_HEADER_UNIT_SETS"_s), + FileSetEntries("INTERFACE_CXX_MODULE_HEADER_UNIT_SETS"_s)) { } @@ -542,6 +563,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("AUTORCC_OPTIONS"); initProp("LINK_DEPENDS_NO_SHARED"); initProp("LINK_INTERFACE_LIBRARIES"); + initProp("MSVC_DEBUG_INFORMATION_FORMAT"); initProp("MSVC_RUNTIME_LIBRARY"); initProp("WATCOM_RUNTIME_LIBRARY"); initProp("WIN32_EXECUTABLE"); @@ -605,12 +627,16 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("XCODE_SCHEME_THREAD_SANITIZER_STOP"); initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER"); initProp("XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP"); + initProp("XCODE_SCHEME_LAUNCH_CONFIGURATION"); + initProp("XCODE_SCHEME_ENABLE_GPU_API_VALIDATION"); + initProp("XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION"); initProp("XCODE_SCHEME_WORKING_DIRECTORY"); initProp("XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER"); initProp("XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP"); initProp("XCODE_SCHEME_MALLOC_SCRIBBLE"); initProp("XCODE_SCHEME_MALLOC_GUARD_EDGES"); initProp("XCODE_SCHEME_GUARD_MALLOC"); + initProp("XCODE_SCHEME_LAUNCH_MODE"); initProp("XCODE_SCHEME_ZOMBIE_OBJECTS"); initProp("XCODE_SCHEME_MALLOC_STACK"); initProp("XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE"); @@ -760,6 +786,10 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, } } + if (this->IsImported() || mf->GetPropertyAsBool("SYSTEM")) { + this->SetProperty("SYSTEM", "ON"); + } + for (auto const& prop : mf->GetState()->GetPropertyDefinitions().GetMap()) { if (prop.first.second == cmProperty::TARGET && !prop.second.GetInitializeFromVariable().empty()) { @@ -1223,7 +1253,8 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, ? targetNameGenex(lib) : lib; this->AppendProperty("LINK_LIBRARIES", - this->GetDebugGeneratorExpressions(libName, llt)); + this->GetDebugGeneratorExpressions(libName, llt), + mf.GetBacktrace()); } if (cmGeneratorExpression::Find(lib) != std::string::npos || @@ -1367,11 +1398,32 @@ cmBTStringRange cmTarget::GetHeaderSetsEntries() const return cmMakeRange(this->impl->HeadersFileSets.SelfEntries.Entries); } +cmBTStringRange cmTarget::GetCxxModuleSetsEntries() const +{ + return cmMakeRange(this->impl->CxxModulesFileSets.SelfEntries.Entries); +} + +cmBTStringRange cmTarget::GetCxxModuleHeaderSetsEntries() const +{ + return cmMakeRange(this->impl->CxxModuleHeadersFileSets.SelfEntries.Entries); +} + cmBTStringRange cmTarget::GetInterfaceHeaderSetsEntries() const { return cmMakeRange(this->impl->HeadersFileSets.InterfaceEntries.Entries); } +cmBTStringRange cmTarget::GetInterfaceCxxModuleSetsEntries() const +{ + return cmMakeRange(this->impl->CxxModulesFileSets.InterfaceEntries.Entries); +} + +cmBTStringRange cmTarget::GetInterfaceCxxModuleHeaderSetsEntries() const +{ + return cmMakeRange( + this->impl->CxxModuleHeadersFileSets.InterfaceEntries.Entries); +} + namespace { #define MAKE_PROP(PROP) const std::string prop##PROP = #PROP MAKE_PROP(C_STANDARD); @@ -1631,13 +1683,21 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value) } else if (this->impl->HeadersFileSets.WriteProperties( this, this->impl.get(), prop, value, true)) { /* Handled in the `if` condition. */ + } else if (this->impl->CxxModulesFileSets.WriteProperties( + this, this->impl.get(), prop, value, true)) { + /* Handled in the `if` condition. */ + } else if (this->impl->CxxModuleHeadersFileSets.WriteProperties( + this, this->impl.get(), prop, value, true)) { + /* Handled in the `if` condition. */ } else { this->impl->Properties.SetProperty(prop, value); } } void cmTarget::AppendProperty(const std::string& prop, - const std::string& value, bool asString) + const std::string& value, + cm::optional<cmListFileBacktrace> const& bt, + bool asString) { if (prop == "NAME") { this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, @@ -1668,32 +1728,32 @@ void cmTarget::AppendProperty(const std::string& prop, } if (prop == "INCLUDE_DIRECTORIES") { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->IncludeDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == "COMPILE_OPTIONS") { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->CompileOptionsEntries.emplace_back(value, lfbt); } } else if (prop == "COMPILE_FEATURES") { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->CompileFeaturesEntries.emplace_back(value, lfbt); } } else if (prop == "COMPILE_DEFINITIONS") { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->CompileDefinitionsEntries.emplace_back(value, lfbt); } } else if (prop == "LINK_OPTIONS") { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->LinkOptionsEntries.emplace_back(value, lfbt); } } else if (prop == "LINK_DIRECTORIES") { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->LinkDirectoriesEntries.emplace_back(value, lfbt); } } else if (prop == "PRECOMPILE_HEADERS") { @@ -1706,32 +1766,32 @@ void cmTarget::AppendProperty(const std::string& prop, return; } if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->PrecompileHeadersEntries.emplace_back(value, lfbt); } } else if (prop == "LINK_LIBRARIES") { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->LinkImplementationPropertyEntries.emplace_back(value, lfbt); } } else if (prop == propINTERFACE_LINK_LIBRARIES) { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->LinkInterfacePropertyEntries.emplace_back(value, lfbt); } } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT) { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->LinkInterfaceDirectPropertyEntries.emplace_back(value, lfbt); } } else if (prop == propINTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE) { if (!value.empty()) { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->LinkInterfaceDirectExcludePropertyEntries.emplace_back(value, lfbt); } } else if (prop == "SOURCES") { - cmListFileBacktrace lfbt = this->impl->Makefile->GetBacktrace(); + cmListFileBacktrace lfbt = this->impl->GetBacktrace(bt); this->impl->SourceEntries.emplace_back(value, lfbt); } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME")) { this->impl->Makefile->IssueMessage( @@ -1742,6 +1802,13 @@ void cmTarget::AppendProperty(const std::string& prop, this->impl->Makefile->IssueMessage( MessageType::FATAL_ERROR, prop + " property may not be appended."); } else if (this->impl->HeadersFileSets.WriteProperties( + this, this->impl.get(), prop, value, + false)) { // NOLINT(bugprone-branch-clone) + /* Handled in the `if` condition. */ + } else if (this->impl->CxxModulesFileSets.WriteProperties( + this, this->impl.get(), prop, value, false)) { + /* Handled in the `if` condition. */ + } else if (this->impl->CxxModuleHeadersFileSets.WriteProperties( this, this->impl.get(), prop, value, false)) { /* Handled in the `if` condition. */ } else { @@ -2307,6 +2374,17 @@ cmValue cmTarget::GetProperty(const std::string& prop) const if (headers.first) { return headers.second; } + auto cxx_modules = this->impl->CxxModulesFileSets.ReadProperties( + this, this->impl.get(), prop); + if (cxx_modules.first) { + return cxx_modules.second; + } + auto cxx_module_headers = + this->impl->CxxModuleHeadersFileSets.ReadProperties( + this, this->impl.get(), prop); + if (cxx_module_headers.first) { + return cxx_module_headers.second; + } } cmValue retVal = this->impl->Properties.GetPropertyValue(prop); @@ -2584,6 +2662,11 @@ std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet( auto bt = this->impl->Makefile->GetBacktrace(); if (type == this->impl->HeadersFileSets.TypeName) { this->impl->HeadersFileSets.AddFileSet(name, vis, std::move(bt)); + } else if (type == this->impl->CxxModulesFileSets.TypeName) { + this->impl->CxxModulesFileSets.AddFileSet(name, vis, std::move(bt)); + } else if (type == this->impl->CxxModuleHeadersFileSets.TypeName) { + this->impl->CxxModuleHeadersFileSets.AddFileSet(name, vis, + std::move(bt)); } } return std::make_pair(&result.first->second, result.second); @@ -2594,6 +2677,12 @@ std::string cmTarget::GetFileSetsPropertyName(const std::string& type) if (type == "HEADERS") { return "HEADER_SETS"; } + if (type == "CXX_MODULES") { + return "CXX_MODULE_SETS"; + } + if (type == "CXX_MODULE_HEADER_UNITS") { + return "CXX_MODULE_HEADER_UNIT_SETS"; + } return ""; } @@ -2602,6 +2691,12 @@ std::string cmTarget::GetInterfaceFileSetsPropertyName(const std::string& type) if (type == "HEADERS") { return "INTERFACE_HEADER_SETS"; } + if (type == "CXX_MODULES") { + return "INTERFACE_CXX_MODULE_SETS"; + } + if (type == "CXX_MODULE_HEADER_UNITS") { + return "INTERFACE_CXX_MODULE_HEADER_UNIT_SETS"; + } return ""; } @@ -2629,6 +2724,8 @@ std::vector<std::string> cmTarget::GetAllInterfaceFileSets() const }; appendEntries(this->impl->HeadersFileSets.InterfaceEntries.Entries); + appendEntries(this->impl->CxxModulesFileSets.InterfaceEntries.Entries); + appendEntries(this->impl->CxxModuleHeadersFileSets.InterfaceEntries.Entries); return result; } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 467c4da..38bd036 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -185,8 +185,10 @@ public: { this->SetProperty(prop, cmValue(value)); } - void AppendProperty(const std::string& prop, const std::string& value, - bool asString = false); + void AppendProperty( + const std::string& prop, const std::string& value, + cm::optional<cmListFileBacktrace> const& bt = cm::nullopt, + bool asString = false); //! Might return a nullptr if the property is not set or invalid cmValue GetProperty(const std::string& prop) const; //! Always returns a valid pointer @@ -281,8 +283,12 @@ public: cmBTStringRange GetLinkInterfaceDirectExcludeEntries() const; cmBTStringRange GetHeaderSetsEntries() const; + cmBTStringRange GetCxxModuleSetsEntries() const; + cmBTStringRange GetCxxModuleHeaderSetsEntries() const; cmBTStringRange GetInterfaceHeaderSetsEntries() const; + cmBTStringRange GetInterfaceCxxModuleSetsEntries() const; + cmBTStringRange GetInterfaceCxxModuleHeaderSetsEntries() const; std::string ImportedGetFullPath(const std::string& config, cmStateEnums::ArtifactType artifact) const; diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx index b56b245..268bfac 100644 --- a/Source/cmTargetCompileDefinitionsCommand.cxx +++ b/Source/cmTargetCompileDefinitionsCommand.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTargetCompileDefinitionsCommand.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmStringAlgorithms.h" @@ -28,7 +29,8 @@ private: const std::vector<std::string>& content, bool /*prepend*/, bool /*system*/) override { - tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content)); + tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content), + this->Makefile->GetBacktrace()); return true; // Successfully handled. } diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h index 885ac74..1cef888 100644 --- a/Source/cmTargetExport.h +++ b/Source/cmTargetExport.h @@ -8,6 +8,7 @@ class cmFileSet; class cmGeneratorTarget; +class cmInstallCxxModuleBmiGenerator; class cmInstallFileSetGenerator; class cmInstallFilesGenerator; class cmInstallTargetGenerator; @@ -32,6 +33,7 @@ public: cmInstallTargetGenerator* BundleGenerator; cmInstallFilesGenerator* HeaderGenerator; std::map<cmFileSet*, cmInstallFileSetGenerator*> FileSetGenerators; + cmInstallCxxModuleBmiGenerator* CxxModuleBmiGenerator; ///@} bool NamelinkOnly = false; diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx index b4b4319..cb83873 100644 --- a/Source/cmTargetIncludeDirectoriesCommand.cxx +++ b/Source/cmTargetIncludeDirectoriesCommand.cxx @@ -88,7 +88,8 @@ void TargetIncludeDirectoriesImpl::HandleInterfaceContent( system); if (system) { std::string joined = this->Join(content); - tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", joined); + tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES", joined, + this->Makefile->GetBacktrace()); } } diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index af870da..0b123b2 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -622,7 +622,7 @@ bool TLL::HandleLibrary(ProcessingState currentProcessingState, void TLL::AppendProperty(std::string const& prop, std::string const& value) { this->AffectsProperty(prop); - this->Target->AppendProperty(prop, value); + this->Target->AppendProperty(prop, value, this->Makefile.GetBacktrace()); } void TLL::AffectsProperty(std::string const& prop) @@ -633,14 +633,16 @@ void TLL::AffectsProperty(std::string const& prop) // Add a wrapper to the expression to tell LookupLinkItem to look up // names in the caller's directory. if (this->Props.insert(prop).second) { - this->Target->AppendProperty(prop, this->DirectoryId); + this->Target->AppendProperty(prop, this->DirectoryId, + this->Makefile.GetBacktrace()); } } TLL::~TLL() { for (std::string const& prop : this->Props) { - this->Target->AppendProperty(prop, CMAKE_DIRECTORY_ID_SEP); + this->Target->AppendProperty(prop, CMAKE_DIRECTORY_ID_SEP, + this->Makefile.GetBacktrace()); } } diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx index a5066cc..4dd158d 100644 --- a/Source/cmTargetPrecompileHeadersCommand.cxx +++ b/Source/cmTargetPrecompileHeadersCommand.cxx @@ -5,6 +5,7 @@ #include <utility> #include "cmGeneratorExpression.h" +#include "cmListFileCache.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmStringAlgorithms.h" @@ -48,7 +49,8 @@ private: { std::string const& base = this->Makefile->GetCurrentSourceDirectory(); tgt->AppendProperty("PRECOMPILE_HEADERS", - this->Join(ConvertToAbsoluteContent(content, base))); + this->Join(ConvertToAbsoluteContent(content, base)), + this->Makefile->GetBacktrace()); return true; } diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx index b1367e1..53e25b5 100644 --- a/Source/cmTargetSourcesCommand.cxx +++ b/Source/cmTargetSourcesCommand.cxx @@ -9,6 +9,8 @@ #include <cmext/string_view> #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" +#include "cmExperimental.h" #include "cmFileSet.h" #include "cmGeneratorExpression.h" #include "cmListFileCache.h" @@ -27,8 +29,8 @@ struct FileSetArgs { std::string Type; std::string FileSet; - std::vector<std::string> BaseDirs; - std::vector<std::string> Files; + ArgumentParser::MaybeEmpty<std::vector<std::string>> BaseDirs; + ArgumentParser::MaybeEmpty<std::vector<std::string>> Files; }; auto const FileSetArgsParser = cmArgumentParser<FileSetArgs>() @@ -77,7 +79,8 @@ private: { tgt->AppendProperty("SOURCES", this->Join(this->ConvertToAbsoluteContent( - tgt, content, IsInterface::No, CheckCMP0076::Yes))); + tgt, content, IsInterface::No, CheckCMP0076::Yes)), + this->Makefile->GetBacktrace()); return true; // Successfully handled. } @@ -196,7 +199,7 @@ std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent( bool TargetSourcesImpl::HandleFileSetMode( const std::string& scope, const std::vector<std::string>& content) { - auto args = FileSetsArgsParser.Parse(content); + auto args = FileSetsArgsParser.Parse(content, /*unparsedArguments=*/nullptr); for (auto& argList : args.FileSets) { argList.emplace(argList.begin(), "FILE_SET"_s); @@ -256,9 +259,31 @@ bool TargetSourcesImpl::HandleOneFileSet( this->SetError("Must specify a TYPE when creating file set"); return false; } - if (type != "HEADERS"_s) { - this->SetError("File set TYPE may only be \"HEADERS\""); - return false; + bool const supportCxx20FileSetTypes = cmExperimental::HasSupportEnabled( + *this->Makefile, cmExperimental::Feature::CxxModuleCMakeApi); + + if (supportCxx20FileSetTypes) { + if (type != "HEADERS"_s && type != "CXX_MODULES"_s && + type != "CXX_MODULE_HEADER_UNITS"_s) { + this->SetError( + R"(File set TYPE may only be "HEADERS", "CXX_MODULES", or "CXX_MODULE_HEADER_UNITS")"); + return false; + } + + if (cmFileSetVisibilityIsForInterface(visibility) && + !cmFileSetVisibilityIsForSelf(visibility) && + !this->Target->IsImported()) { + if (type == "CXX_MODULES"_s || type == "CXX_MODULE_HEADER_UNITS"_s) { + this->SetError( + R"(File set TYPEs "CXX_MODULES" and "CXX_MODULE_HEADER_UNITS" may not have "INTERFACE" visibility)"); + return false; + } + } + } else { + if (type != "HEADERS"_s) { + this->SetError("File set TYPE may only be \"HEADERS\""); + return false; + } } if (args.BaseDirs.empty()) { @@ -294,17 +319,19 @@ bool TargetSourcesImpl::HandleOneFileSet( if (!baseDirectories.empty()) { fileSet.first->AddDirectoryEntry( BT<std::string>(baseDirectories, this->Makefile->GetBacktrace())); - if (type == "HEADERS"_s) { + if (type == "HEADERS"_s || type == "CXX_MODULE_HEADER_UNITS"_s) { for (auto const& dir : cmExpandedList(baseDirectories)) { auto interfaceDirectoriesGenex = cmStrCat("$<BUILD_INTERFACE:", dir, ">"); if (cmFileSetVisibilityIsForSelf(visibility)) { this->Target->AppendProperty("INCLUDE_DIRECTORIES", - interfaceDirectoriesGenex); + interfaceDirectoriesGenex, + this->Makefile->GetBacktrace()); } if (cmFileSetVisibilityIsForInterface(visibility)) { this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES", - interfaceDirectoriesGenex); + interfaceDirectoriesGenex, + this->Makefile->GetBacktrace()); } } } diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx index 130c228..a2c4ce1 100644 --- a/Source/cmTryCompileCommand.cxx +++ b/Source/cmTryCompileCommand.cxx @@ -2,34 +2,69 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmTryCompileCommand.h" +#include "cmCoreTryCompile.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" +#include "cmRange.h" +#include "cmState.h" +#include "cmStateTypes.h" +#include "cmStringAlgorithms.h" +#include "cmValue.h" #include "cmake.h" -class cmExecutionStatus; - -// cmTryCompileCommand -bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv, - cmExecutionStatus&) +bool cmTryCompileCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) { - if (argv.size() < 3) { + cmMakefile& mf = status.GetMakefile(); + + if (args.size() < 3) { + mf.IssueMessage( + MessageType::FATAL_ERROR, + "The try_compile() command requires at least 3 arguments."); return false; } - if (this->Makefile->GetCMakeInstance()->GetWorkingMode() == - cmake::FIND_PACKAGE_MODE) { - this->Makefile->IssueMessage( + if (mf.GetCMakeInstance()->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) { + mf.IssueMessage( MessageType::FATAL_ERROR, "The try_compile() command is not supported in --find-package mode."); return false; } - this->TryCompileCode(argv, false); + cmStateEnums::TargetType targetType = cmStateEnums::EXECUTABLE; + cmValue tt = mf.GetDefinition("CMAKE_TRY_COMPILE_TARGET_TYPE"); + if (cmNonempty(tt)) { + if (*tt == cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE)) { + targetType = cmStateEnums::EXECUTABLE; + } else if (*tt == + cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY)) { + targetType = cmStateEnums::STATIC_LIBRARY; + } else { + mf.IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Invalid value '", *tt, + "' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only '", + cmState::GetTargetTypeName(cmStateEnums::EXECUTABLE), + "' and '", + cmState::GetTargetTypeName(cmStateEnums::STATIC_LIBRARY), + "' are allowed.")); + return false; + } + } + + cmCoreTryCompile tc(&mf); + cmCoreTryCompile::Arguments arguments = + tc.ParseArgs(cmMakeRange(args), false); + if (!arguments) { + return true; + } + tc.TryCompileCode(arguments, targetType); // if They specified clean then we clean up what we can - if (this->SrcFileSignature) { - if (!this->Makefile->GetCMakeInstance()->GetDebugTryCompile()) { - this->CleanupFiles(this->BinaryDirectory); + if (tc.SrcFileSignature) { + if (!mf.GetCMakeInstance()->GetDebugTryCompile()) { + tc.CleanupFiles(tc.BinaryDirectory); } } return true; diff --git a/Source/cmTryCompileCommand.h b/Source/cmTryCompileCommand.h index d8cc16e..6a3430b 100644 --- a/Source/cmTryCompileCommand.h +++ b/Source/cmTryCompileCommand.h @@ -7,33 +7,7 @@ #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" -#include "cmCoreTryCompile.h" - class cmExecutionStatus; -/** \class cmTryCompileCommand - * \brief Specifies where to install some files - * - * cmTryCompileCommand is used to test if source code can be compiled - */ -class cmTryCompileCommand : public cmCoreTryCompile -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmTryCompileCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; -}; +bool cmTryCompileCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index c82ac64..1e81195 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -4,9 +4,14 @@ #include <cstdio> +#include <cm/optional> + #include "cmsys/FStream.hxx" +#include "cmArgumentParserTypes.h" +#include "cmCoreTryCompile.h" #include "cmDuration.h" +#include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmRange.h" @@ -17,157 +22,157 @@ #include "cmValue.h" #include "cmake.h" -class cmExecutionStatus; +namespace { -// cmTryRunCommand -bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, - cmExecutionStatus&) +class TryRunCommandImpl : public cmCoreTryCompile { - if (argv.size() < 4) { - return false; - } - - if (this->Makefile->GetCMakeInstance()->GetWorkingMode() == - cmake::FIND_PACKAGE_MODE) { - this->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - "The try_run() command is not supported in --find-package mode."); - return false; +public: + TryRunCommandImpl(cmMakefile* mf) + : cmCoreTryCompile(mf) + { } - // build an arg list for TryCompile and extract the runArgs, - std::vector<std::string> tryCompile; - - this->CompileResultVariable.clear(); - this->RunResultVariable.clear(); - this->OutputVariable.clear(); - this->RunOutputVariable.clear(); - this->CompileOutputVariable.clear(); - - std::string runArgs; - unsigned int i; - for (i = 1; i < argv.size(); ++i) { - if (argv[i] == "ARGS") { - ++i; - while (i < argv.size() && argv[i] != "COMPILE_DEFINITIONS" && - argv[i] != "CMAKE_FLAGS" && argv[i] != "LINK_OPTIONS" && - argv[i] != "LINK_LIBRARIES") { - runArgs += " "; - runArgs += argv[i]; - ++i; - } - if (i < argv.size()) { - tryCompile.push_back(argv[i]); - } - } else { - if (argv[i] == "OUTPUT_VARIABLE") { - if (argv.size() <= (i + 1)) { - cmSystemTools::Error( - "OUTPUT_VARIABLE specified but there is no variable"); - return false; - } - i++; - this->OutputVariable = argv[i]; - } else if (argv[i] == "RUN_OUTPUT_VARIABLE") { - if (argv.size() <= (i + 1)) { - cmSystemTools::Error( - "RUN_OUTPUT_VARIABLE specified but there is no variable"); - return false; - } - i++; - this->RunOutputVariable = argv[i]; - } else if (argv[i] == "COMPILE_OUTPUT_VARIABLE") { - if (argv.size() <= (i + 1)) { - cmSystemTools::Error( - "COMPILE_OUTPUT_VARIABLE specified but there is no variable"); - return false; - } - i++; - this->CompileOutputVariable = argv[i]; - } else if (argv[i] == "WORKING_DIRECTORY") { - if (argv.size() <= (i + 1)) { - cmSystemTools::Error( - "WORKING_DIRECTORY specified but there is no variable"); - return false; - } - i++; - this->WorkingDirectory = argv[i]; - } else { - tryCompile.push_back(argv[i]); - } - } + bool TryRunCode(std::vector<std::string> const& args); + + void RunExecutable(const std::string& runArgs, + cm::optional<std::string> const& workDir, + std::string* runOutputContents, + std::string* runOutputStdOutContents, + std::string* runOutputStdErrContents); + void DoNotRunExecutable(const std::string& runArgs, + const std::string& srcFile, + std::string const& compileResultVariable, + std::string* runOutputContents, + std::string* runOutputStdOutContents, + std::string* runOutputStdErrContents); + + bool NoCache; + std::string RunResultVariable; +}; + +bool TryRunCommandImpl::TryRunCode(std::vector<std::string> const& argv) +{ + this->RunResultVariable = argv[0]; + cmCoreTryCompile::Arguments arguments = + this->ParseArgs(cmMakeRange(argv).advance(1), true); + if (!arguments) { + return true; } + this->NoCache = arguments.NoCache; // although they could be used together, don't allow it, because // using OUTPUT_VARIABLE makes crosscompiling harder - if (!this->OutputVariable.empty() && - (!this->RunOutputVariable.empty() || - !this->CompileOutputVariable.empty())) { + if (arguments.OutputVariable && + (arguments.CompileOutputVariable || arguments.RunOutputVariable || + arguments.RunOutputStdOutVariable || + arguments.RunOutputStdErrVariable)) { cmSystemTools::Error( "You cannot use OUTPUT_VARIABLE together with COMPILE_OUTPUT_VARIABLE " - "or RUN_OUTPUT_VARIABLE. Please use only COMPILE_OUTPUT_VARIABLE and/or " - "RUN_OUTPUT_VARIABLE."); + ", RUN_OUTPUT_VARIABLE, RUN_OUTPUT_STDOUT_VARIABLE or " + "RUN_OUTPUT_STDERR_VARIABLE. " + "Please use only COMPILE_OUTPUT_VARIABLE, RUN_OUTPUT_VARIABLE, " + "RUN_OUTPUT_STDOUT_VARIABLE " + "and/or RUN_OUTPUT_STDERR_VARIABLE."); + return false; + } + + if ((arguments.RunOutputStdOutVariable || + arguments.RunOutputStdErrVariable) && + arguments.RunOutputVariable) { + cmSystemTools::Error( + "You cannot use RUN_OUTPUT_STDOUT_VARIABLE or " + "RUN_OUTPUT_STDERR_VARIABLE together " + "with RUN_OUTPUT_VARIABLE. Please use only COMPILE_OUTPUT_VARIABLE or " + "RUN_OUTPUT_STDOUT_VARIABLE and/or RUN_OUTPUT_STDERR_VARIABLE."); return false; } - if (!this->WorkingDirectory.empty()) { - if (!cmSystemTools::MakeDirectory(this->WorkingDirectory)) { + if (arguments.RunWorkingDirectory) { + if (!cmSystemTools::MakeDirectory(*arguments.RunWorkingDirectory)) { cmSystemTools::Error(cmStrCat("Error creating working directory \"", - this->WorkingDirectory, "\".")); + *arguments.RunWorkingDirectory, "\".")); return false; } } bool captureRunOutput = false; - if (!this->OutputVariable.empty()) { + bool captureRunOutputStdOutErr = false; + if (arguments.OutputVariable) { captureRunOutput = true; - tryCompile.emplace_back("OUTPUT_VARIABLE"); - tryCompile.push_back(this->OutputVariable); + } else if (arguments.CompileOutputVariable) { + arguments.OutputVariable = arguments.CompileOutputVariable; } - if (!this->CompileOutputVariable.empty()) { - tryCompile.emplace_back("OUTPUT_VARIABLE"); - tryCompile.push_back(this->CompileOutputVariable); - } - if (!this->RunOutputVariable.empty()) { + if (arguments.RunOutputStdOutVariable || arguments.RunOutputStdErrVariable) { + captureRunOutputStdOutErr = true; + } else if (arguments.RunOutputVariable) { captureRunOutput = true; } - this->RunResultVariable = argv[0]; - this->CompileResultVariable = argv[1]; - // do the try compile - int res = this->TryCompileCode(tryCompile, true); + bool compiled = this->TryCompileCode(arguments, cmStateEnums::EXECUTABLE); // now try running the command if it compiled - if (!res) { + if (compiled) { if (this->OutputFile.empty()) { cmSystemTools::Error(this->FindErrorMessage); } else { + std::string runArgs; + if (arguments.RunArgs) { + runArgs = cmStrCat(" ", cmJoin(*arguments.RunArgs, " ")); + } + // "run" it and capture the output std::string runOutputContents; + std::string runOutputStdOutContents; + std::string runOutputStdErrContents; if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING") && !this->Makefile->IsDefinitionSet("CMAKE_CROSSCOMPILING_EMULATOR")) { this->DoNotRunExecutable( - runArgs, argv[3], captureRunOutput ? &runOutputContents : nullptr); + runArgs, *arguments.SourceDirectoryOrFile, + *arguments.CompileResultVariable, + captureRunOutput ? &runOutputContents : nullptr, + captureRunOutputStdOutErr && arguments.RunOutputStdOutVariable + ? &runOutputStdOutContents + : nullptr, + captureRunOutputStdOutErr && arguments.RunOutputStdErrVariable + ? &runOutputStdErrContents + : nullptr); } else { - this->RunExecutable(runArgs, &runOutputContents); + this->RunExecutable( + runArgs, arguments.RunWorkingDirectory, + captureRunOutput ? &runOutputContents : nullptr, + captureRunOutputStdOutErr && arguments.RunOutputStdOutVariable + ? &runOutputStdOutContents + : nullptr, + captureRunOutputStdOutErr && arguments.RunOutputStdErrVariable + ? &runOutputStdErrContents + : nullptr); } // now put the output into the variables - if (!this->RunOutputVariable.empty()) { - this->Makefile->AddDefinition(this->RunOutputVariable, + if (arguments.RunOutputVariable) { + this->Makefile->AddDefinition(*arguments.RunOutputVariable, runOutputContents); } + if (arguments.RunOutputStdOutVariable) { + this->Makefile->AddDefinition(*arguments.RunOutputStdOutVariable, + runOutputStdOutContents); + } + if (arguments.RunOutputStdErrVariable) { + this->Makefile->AddDefinition(*arguments.RunOutputStdErrVariable, + runOutputStdErrContents); + } - if (!this->OutputVariable.empty()) { + if (arguments.OutputVariable && !arguments.CompileOutputVariable) { // if the TryCompileCore saved output in this outputVariable then // prepend that output to this output cmValue compileOutput = - this->Makefile->GetDefinition(this->OutputVariable); + this->Makefile->GetDefinition(*arguments.OutputVariable); if (compileOutput) { runOutputContents = *compileOutput + runOutputContents; } - this->Makefile->AddDefinition(this->OutputVariable, runOutputContents); + this->Makefile->AddDefinition(*arguments.OutputVariable, + runOutputContents); } } } @@ -179,8 +184,10 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv, return true; } -void cmTryRunCommand::RunExecutable(const std::string& runArgs, - std::string* out) +void TryRunCommandImpl::RunExecutable(const std::string& runArgs, + cm::optional<std::string> const& workDir, + std::string* out, std::string* stdOut, + std::string* stdErr) { int retVal = -1; @@ -204,9 +211,10 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs, finalCommand += runArgs; } bool worked = cmSystemTools::RunSingleCommand( - finalCommand, out, out, &retVal, - this->WorkingDirectory.empty() ? nullptr : this->WorkingDirectory.c_str(), - cmSystemTools::OUTPUT_NONE, cmDuration::zero()); + finalCommand, stdOut || stdErr ? stdOut : out, + stdOut || stdErr ? stdErr : out, &retVal, + workDir ? workDir->c_str() : nullptr, cmSystemTools::OUTPUT_NONE, + cmDuration::zero()); // set the run var char retChar[16]; const char* retStr; @@ -216,18 +224,23 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs, } else { retStr = "FAILED_TO_RUN"; } - this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr, - "Result of try_run()", - cmStateEnums::INTERNAL); + if (this->NoCache) { + this->Makefile->AddDefinition(this->RunResultVariable, retStr); + } else { + this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr, + "Result of try_run()", + cmStateEnums::INTERNAL); + } } /* This is only used when cross compiling. Instead of running the executable, two cache variables are created which will hold the results the executable would have produced. */ -void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, - const std::string& srcFile, - std::string* out) +void TryRunCommandImpl::DoNotRunExecutable( + const std::string& runArgs, const std::string& srcFile, + std::string const& compileResultVariable, std::string* out, + std::string* stdOut, std::string* stdErr) { // copy the executable out of the CMakeFiles/ directory, so it is not // removed at the end of try_run() and the user can run it manually @@ -246,6 +259,10 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, std::string internalRunOutputName = this->RunResultVariable + "__TRYRUN_OUTPUT"; + std::string internalRunOutputStdOutName = + this->RunResultVariable + "__TRYRUN_OUTPUT_STDOUT"; + std::string internalRunOutputStdErrName = + this->RunResultVariable + "__TRYRUN_OUTPUT_STDERR"; bool error = false; if (!this->Makefile->GetDefinition(this->RunResultVariable)) { @@ -269,7 +286,51 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, } // is the output from the executable used ? - if (out) { + if (stdOut || stdErr) { + if (!this->Makefile->GetDefinition(internalRunOutputStdOutName)) { + // if the variables doesn't exist, create it with a helpful error text + // and mark it as advanced + std::string comment = cmStrCat( + "Output of try_run(), contains the text, which the executable " + "would have printed on stdout on its target platform.\n", + detailsString); + + this->Makefile->AddCacheDefinition( + internalRunOutputStdOutName, "PLEASE_FILL_OUT-NOTFOUND", + comment.c_str(), cmStateEnums::STRING); + cmState* state = this->Makefile->GetState(); + cmValue existing = + state->GetCacheEntryValue(internalRunOutputStdOutName); + if (existing) { + state->SetCacheEntryProperty(internalRunOutputStdOutName, "ADVANCED", + "1"); + } + + error = true; + } + + if (!this->Makefile->GetDefinition(internalRunOutputStdErrName)) { + // if the variables doesn't exist, create it with a helpful error text + // and mark it as advanced + std::string comment = cmStrCat( + "Output of try_run(), contains the text, which the executable " + "would have printed on stderr on its target platform.\n", + detailsString); + + this->Makefile->AddCacheDefinition( + internalRunOutputStdErrName, "PLEASE_FILL_OUT-NOTFOUND", + comment.c_str(), cmStateEnums::STRING); + cmState* state = this->Makefile->GetState(); + cmValue existing = + state->GetCacheEntryValue(internalRunOutputStdErrName); + if (existing) { + state->SetCacheEntryProperty(internalRunOutputStdErrName, "ADVANCED", + "1"); + } + + error = true; + } + } else if (out) { if (!this->Makefile->GetDefinition(internalRunOutputName)) { // if the variables doesn't exist, create it with a helpful error text // and mark it as advanced @@ -317,7 +378,34 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, " to\n" " the exit code (in many cases 0 for success), otherwise " "enter \"FAILED_TO_RUN\".\n"); - if (out) { + if (stdOut || stdErr) { + if (stdOut) { + comment += internalRunOutputStdOutName; + comment += + "\n contains the text the executable " + "would have printed on stdout.\n" + " If the executable would not have been able to run, set "; + comment += internalRunOutputStdOutName; + comment += " empty.\n" + " Otherwise check if the output is evaluated by the " + "calling CMake code. If so,\n" + " check what the source file would have printed when " + "called with the given arguments.\n"; + } + if (stdErr) { + comment += internalRunOutputStdErrName; + comment += + "\n contains the text the executable " + "would have printed on stderr.\n" + " If the executable would not have been able to run, set "; + comment += internalRunOutputStdErrName; + comment += " empty.\n" + " Otherwise check if the output is evaluated by the " + "calling CMake code. If so,\n" + " check what the source file would have printed when " + "called with the given arguments.\n"; + } + } else if (out) { comment += internalRunOutputName; comment += "\n contains the text the executable " @@ -330,8 +418,9 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, " check what the source file would have printed when " "called with the given arguments.\n"; } + comment += "The "; - comment += this->CompileResultVariable; + comment += compileResultVariable; comment += " variable holds the build result for this try_run().\n\n" "Source file : "; comment += srcFile + "\n"; @@ -370,7 +459,37 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, return; } - if (out) { + if (stdOut || stdErr) { + if (stdOut) { + (*stdOut) = *this->Makefile->GetDefinition(internalRunOutputStdOutName); + } + if (stdErr) { + (*stdErr) = *this->Makefile->GetDefinition(internalRunOutputStdErrName); + } + } else if (out) { (*out) = *this->Makefile->GetDefinition(internalRunOutputName); } } +} + +bool cmTryRunCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + cmMakefile& mf = status.GetMakefile(); + + if (args.size() < 4) { + mf.IssueMessage(MessageType::FATAL_ERROR, + "The try_run() command requires at least 4 arguments."); + return false; + } + + if (mf.GetCMakeInstance()->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) { + mf.IssueMessage( + MessageType::FATAL_ERROR, + "The try_run() command is not supported in --find-package mode."); + return false; + } + + TryRunCommandImpl tr(&mf); + return tr.TryRunCode(args); +} diff --git a/Source/cmTryRunCommand.h b/Source/cmTryRunCommand.h index d45acd8..38e3638 100644 --- a/Source/cmTryRunCommand.h +++ b/Source/cmTryRunCommand.h @@ -7,47 +7,7 @@ #include <string> #include <vector> -#include <cm/memory> - -#include "cmCommand.h" -#include "cmCoreTryCompile.h" - class cmExecutionStatus; -/** \class cmTryRunCommand - * \brief Specifies where to install some files - * - * cmTryRunCommand is used to test if source code can be compiled - */ -class cmTryRunCommand : public cmCoreTryCompile -{ -public: - /** - * This is a virtual constructor for the command. - */ - std::unique_ptr<cmCommand> Clone() override - { - return cm::make_unique<cmTryRunCommand>(); - } - - /** - * This is called when the command is first encountered in - * the CMakeLists.txt file. - */ - bool InitialPass(std::vector<std::string> const& args, - cmExecutionStatus& status) override; - -private: - void RunExecutable(const std::string& runArgs, - std::string* runOutputContents); - void DoNotRunExecutable(const std::string& runArgs, - const std::string& srcFile, - std::string* runOutputContents); - - std::string CompileResultVariable; - std::string RunResultVariable; - std::string OutputVariable; - std::string RunOutputVariable; - std::string CompileOutputVariable; - std::string WorkingDirectory; -}; +bool cmTryRunCommand(std::vector<std::string> const& args, + cmExecutionStatus& status); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 9f3d620..c09eefa 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -354,6 +354,18 @@ std::ostream& cmVisualStudio10TargetGenerator::Elem::WriteString( void cmVisualStudio10TargetGenerator::Generate() { + for (std::string const& config : this->Configurations) { + this->GeneratorTarget->CheckCxxModuleStatus(config); + } + + if (this->GeneratorTarget->HaveCxx20ModuleSources()) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("The \"", this->GeneratorTarget->GetName(), + "\" target contains C++ module sources which are not supported " + "by the generator")); + } + this->ProjectType = computeProjectType(this->GeneratorTarget); this->Managed = this->ProjectType == VsProjectType::csproj; const std::string ProjectFileExtension = @@ -483,7 +495,7 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile( e1.Element("PreferredToolArchitecture", hostArch); } - // ALL_BUILD and ZERO_CHECK projects transitively include + // The ALL_BUILD, PACKAGE, and ZERO_CHECK projects transitively include // Microsoft.Common.CurrentVersion.targets which triggers Target // ResolveNugetPackageAssets when SDK-style targets are in the project. // However, these projects have no nuget packages to reference and the @@ -491,7 +503,7 @@ void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile( // Setting ResolveNugetPackages to false skips this target and the build // succeeds. cm::string_view targetName{ this->GeneratorTarget->GetName() }; - if (targetName == "ALL_BUILD" || + if (targetName == "ALL_BUILD" || targetName == "PACKAGE" || targetName == CMAKE_CHECK_BUILD_SYSTEM_TARGET) { Elem e1(e0, "PropertyGroup"); e1.Element("ResolveNugetPackages", "false"); @@ -891,6 +903,7 @@ void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile( // of the IDE. e1.Element("VCProjectUpgraderObjectName", "NoUpgrade"); e1.Element("ManagedAssembly", "true"); + e1.Element("AppendTargetFrameworkToOutputPath", "false"); cmValue targetFramework = this->GeneratorTarget->GetProperty("DOTNET_TARGET_FRAMEWORK"); @@ -957,6 +970,10 @@ void cmVisualStudio10TargetGenerator::WriteSdkStyleProjectFile( std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/"; ConvertToWindowsSlash(outDir); e1.Element("OutputPath", outDir); + + Options& o = *(this->ClOptions[config]); + OptionsHelper oh(o, e1); + oh.OutputFlagMap(); } this->WriteDotNetDocumentationFile(e0); @@ -1507,6 +1524,10 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( this->ASanEnabledConfigurations.end()) { e1.Element("EnableAsan", "true"); } + if (this->FuzzerEnabledConfigurations.find(config) != + this->FuzzerEnabledConfigurations.end()) { + e1.Element("EnableFuzzer", "true"); + } { auto s = this->SpectreMitigation.find(config); if (s != this->SpectreMitigation.end()) { @@ -1788,11 +1809,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRuleCpp( e2.WritePlatformConfigTag("Command", cond, script); e2.WritePlatformConfigTag("AdditionalInputs", cond, additional_inputs); e2.WritePlatformConfigTag("Outputs", cond, outputs); - if (this->LocalGenerator->GetVersion() > - cmGlobalVisualStudioGenerator::VSVersion::VS10) { - // VS >= 11 let us turn off linking of custom command outputs. - e2.WritePlatformConfigTag("LinkObjects", cond, "false"); - } + // Turn off linking of custom command outputs. + e2.WritePlatformConfigTag("LinkObjects", cond, "false"); if (symbolic && this->LocalGenerator->GetVersion() >= cmGlobalVisualStudioGenerator::VSVersion::VS16) { @@ -2357,28 +2375,6 @@ void cmVisualStudio10TargetGenerator::WriteSource(Elem& e2, // we must use relative paths. bool forceRelative = sf->GetLanguage() == "CUDA"; std::string sourceFile = this->ConvertPath(sf->GetFullPath(), forceRelative); - if (this->LocalGenerator->GetVersion() == - cmGlobalVisualStudioGenerator::VSVersion::VS10 && - cmSystemTools::FileIsFullPath(sourceFile)) { - // Normal path conversion resulted in a full path. VS 10 (but not 11) - // refuses to show the property page in the IDE for a source file with a - // full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a - // relative path but to allow deeper build trees CMake 2.8.[5678] used a - // full path except for custom commands. Custom commands do not work - // without a relative path, but they do not seem to be involved in tools - // with the above behavior. For other sources we now use a relative path - // when the combined path will not be too long so property pages appear. - std::string sourceRel = this->ConvertPath(sf->GetFullPath(), true); - size_t const maxLen = 250; - if (sf->GetCustomCommand() || - ((this->LocalGenerator->GetCurrentBinaryDirectory().length() + 1 + - sourceRel.length()) <= maxLen)) { - forceRelative = true; - sourceFile = sourceRel; - } else { - this->GlobalGenerator->PathTooLong(this->GeneratorTarget, sf, sourceRel); - } - } ConvertToWindowsSlash(sourceFile); e2.Attribute("Include", sourceFile); @@ -2875,7 +2871,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions( Elem& e0) { cmStateEnums::TargetType ttype = this->GeneratorTarget->GetType(); - if (ttype > cmStateEnums::GLOBAL_TARGET) { + if (ttype > cmStateEnums::INTERFACE_LIBRARY) { return; } if (this->ProjectType == VsProjectType::csproj) { @@ -3117,6 +3113,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->LangForClCompile = langForClCompile; if (!langForClCompile.empty()) { this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, + cmBuildStep::Compile, langForClCompile, configName); this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, langForClCompile, configName); @@ -3128,10 +3125,17 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } // Check if ASan is enabled. - if (flags.find("/fsanitize=address") != std::string::npos) { + if (flags.find("/fsanitize=address") != std::string::npos || + flags.find("-fsanitize=address") != std::string::npos) { this->ASanEnabledConfigurations.insert(configName); } + // Check if (lib)Fuzzer is enabled. + if (flags.find("/fsanitize=fuzzer") != std::string::npos || + flags.find("-fsanitize=fuzzer") != std::string::npos) { + this->FuzzerEnabledConfigurations.insert(configName); + } + // Precompile Headers std::string pchHeader = this->GeneratorTarget->GetPchHeader(configName, linkLanguage); @@ -3173,7 +3177,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( // anymore, because cmGeneratorTarget may not be aware that the // target uses C++/CLI. if (flags.find("/clr") != std::string::npos || - defineFlags.find("/clr") != std::string::npos) { + flags.find("-clr") != std::string::npos || + defineFlags.find("/clr") != std::string::npos || + defineFlags.find("-clr") != std::string::npos) { if (configName == this->Configurations[0]) { std::string message = "For the target \"" + this->GeneratorTarget->GetName() + @@ -3492,8 +3498,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( // Get compile flags for CUDA in this directory. std::string flags; - this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, "CUDA", - configName); + this->LocalGenerator->AddLanguageFlags( + flags, this->GeneratorTarget, cmBuildStep::Compile, "CUDA", configName); this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA", configName); @@ -3685,21 +3691,28 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions( this->GeneratorTarget->GetLinkOptions(linkOpts, configName, "CUDA"); // LINK_OPTIONS are escaped. this->LocalGenerator->AppendCompileOptions(linkFlags, linkOpts); + + cmComputeLinkInformation* pcli = + this->GeneratorTarget->GetLinkInformation(configName); + if (doDeviceLinking && pcli) { + + cmLinkLineDeviceComputer computer( + this->LocalGenerator, + this->LocalGenerator->GetStateSnapshot().GetDirectory()); + std::string ignored_; + this->LocalGenerator->GetDeviceLinkFlags(computer, configName, ignored_, + linkFlags, ignored_, ignored_, + this->GeneratorTarget); + + this->LocalGenerator->AddLanguageFlagsForLinking( + linkFlags, this->GeneratorTarget, "CUDA", configName); + } cudaLinkOptions.AppendFlagString("AdditionalOptions", linkFlags); // For static libraries that have device linking enabled compute // the libraries if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY && doDeviceLinking) { - cmComputeLinkInformation* pcli = - this->GeneratorTarget->GetLinkInformation(configName); - if (!pcli) { - cmSystemTools::Error( - "CMake can not compute cmComputeLinkInformation for target: " + - this->Name); - return false; - } - cmComputeLinkInformation& cli = *pcli; cmLinkLineDeviceComputer computer( this->LocalGenerator, @@ -3757,7 +3770,8 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions( std::string flags; this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, - "ASM_MASM", configName); + cmBuildStep::Compile, "ASM_MASM", + configName); masmOptions.Parse(flags); @@ -3809,7 +3823,8 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions( std::string flags; this->LocalGenerator->AddLanguageFlags(flags, this->GeneratorTarget, - "ASM_NASM", configName); + cmBuildStep::Compile, "ASM_NASM", + configName); flags += " -f"; flags += this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT"); nasmOptions.Parse(flags); diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 8d777a3..17dcecd 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -231,6 +231,7 @@ private: bool TargetCompileAsWinRT; std::set<std::string> IPOEnabledConfigurations; std::set<std::string> ASanEnabledConfigurations; + std::set<std::string> FuzzerEnabledConfigurations; std::map<std::string, std::string> SpectreMitigation; cmGlobalVisualStudio10Generator* const GlobalGenerator; cmLocalVisualStudio10Generator* const LocalGenerator; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 00c65ed..e6f5ece 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -75,7 +75,6 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() // the flag to disable exception handling. When the user does // remove the flag we need to override the IDE default of on. switch (this->Version) { - case cmGlobalVisualStudioGenerator::VSVersion::VS10: case cmGlobalVisualStudioGenerator::VSVersion::VS11: case cmGlobalVisualStudioGenerator::VSVersion::VS12: case cmGlobalVisualStudioGenerator::VSVersion::VS14: @@ -101,14 +100,12 @@ void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose) // to the generated project to disable logo suppression. Otherwise // the GUI default is to enable suppression. // - // On Visual Studio 10 (and later!), the value of this attribute should be - // an empty string, instead of "FALSE", in order to avoid a warning: - // "cl ... warning D9035: option 'nologo-' has been deprecated" - // + // On Visual Studio 9, the value of this attribute should be + // "FALSE", instead of an empty string. if (verbose && this->FlagMap.find("SuppressStartupBanner") == this->FlagMap.end()) { this->FlagMap["SuppressStartupBanner"] = - this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS10 ? "FALSE" + this->Version == cmGlobalVisualStudioGenerator::VSVersion::VS9 ? "FALSE" : ""; } } @@ -161,71 +158,12 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() { - // Extract temporary values stored by our flag table. - FlagValue arch = this->TakeFlag("cmake-temp-arch"); - FlagValue code = this->TakeFlag("cmake-temp-code"); - FlagValue gencode = this->TakeFlag("cmake-temp-gencode"); - - // No -code allowed without -arch. - if (arch.empty()) { - code.clear(); - } - - // Create a CodeGeneration field with [arch],[code] syntax in each entry. - // CUDA will convert it to `-gencode=arch=[arch],code="[code],[arch]"`. - FlagValue& result = this->FlagMap["CodeGeneration"]; - - // If there are no flags, leave the CodeGeneration field empty. - if (arch.empty() && gencode.empty()) { - return; - } - - // First entries for the -arch=<arch> [-code=<code>,...] pair. - if (!arch.empty()) { - std::string arch_name = arch[0]; - if (arch_name == "all" || arch_name == "all-major" || - arch_name == "native") { - AppendFlagString("AdditionalOptions", "-arch=" + arch_name); - return; - } - std::vector<std::string> codes; - if (!code.empty()) { - codes = cmTokenize(code[0], ","); - } - if (codes.empty()) { - codes.push_back(arch_name); - // nvcc -arch=<arch> has a special case that allows a real - // architecture to be specified instead of a virtual arch. - // It translates to -arch=<virtual> -code=<real>. - cmSystemTools::ReplaceString(arch_name, "sm_", "compute_"); - } - for (std::string const& c : codes) { - std::string entry = arch_name + "," + c; - result.push_back(entry); - } - } - - // Now add entries for the following signatures: - // -gencode=<arch>,<code> - // -gencode=<arch>,[<code1>,<code2>] - // -gencode=<arch>,"<code1>,<code2>" - for (std::string const& e : gencode) { - std::string entry = e; - cmSystemTools::ReplaceString(entry, "arch=", ""); - cmSystemTools::ReplaceString(entry, "code=", ""); - cmSystemTools::ReplaceString(entry, "[", ""); - cmSystemTools::ReplaceString(entry, "]", ""); - cmSystemTools::ReplaceString(entry, "\"", ""); - - std::vector<std::string> codes = cmTokenize(entry, ","); - if (codes.size() >= 2) { - auto gencode_arch = cm::cbegin(codes); - for (auto ci = gencode_arch + 1; ci != cm::cend(codes); ++ci) { - std::string code_entry = *gencode_arch + "," + *ci; - result.push_back(code_entry); - } - } - } + // Create an empty CodeGeneration field, and pass the the actual + // compile flags via additional options so that we have consistent + // behavior and avoid issues with MSBuild extensions injecting + // virtual code when we request real only. + FlagValue& code_gen_flag = this->FlagMap["CodeGeneration"]; + code_gen_flag = ""; } void cmVisualStudioGeneratorOptions::FixManifestUACFlags() @@ -432,7 +370,7 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( } std::ostringstream oss; - if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) { + if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) { oss << "%(" << tag << ")"; } std::vector<std::string>::const_iterator de = @@ -440,13 +378,13 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions( for (std::string const& di : cmMakeRange(this->Defines.cbegin(), de)) { // Escape the definition for the compiler. std::string define; - if (this->Version < cmGlobalVisualStudioGenerator::VSVersion::VS10) { + if (this->Version == cmGlobalVisualStudioGenerator::VSVersion::VS9) { define = this->LocalGenerator->EscapeForShell(di, true); } else { define = di; } // Escape this flag for the MSBuild. - if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) { + if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) { cmVS10EscapeForMSBuild(define); if (lang == "RC") { cmSystemTools::ReplaceString(define, "\"", "\\\""); @@ -488,7 +426,7 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories( } // Escape this include for the MSBuild. - if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) { + if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) { cmVS10EscapeForMSBuild(include); } oss << sep << include; @@ -500,7 +438,7 @@ void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories( } } - if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) { + if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) { oss << sep << "%(" << tag << ")"; } @@ -514,7 +452,7 @@ void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout, std::ostringstream oss; const char* sep = ""; for (std::string i : m.second) { - if (this->Version >= cmGlobalVisualStudioGenerator::VSVersion::VS10) { + if (this->Version != cmGlobalVisualStudioGenerator::VSVersion::VS9) { cmVS10EscapeForMSBuild(i); } oss << sep << i; diff --git a/Source/cmWhileCommand.cxx b/Source/cmWhileCommand.cxx index fb94273..e80d1fc 100644 --- a/Source/cmWhileCommand.cxx +++ b/Source/cmWhileCommand.cxx @@ -96,7 +96,7 @@ bool cmWhileFunctionBlocker::Replay(std::vector<cmListFileFunction> functions, cmExecutionStatus status(mf); mf.ExecuteCommand(fn, status); if (status.GetReturnInvoked()) { - inStatus.SetReturnInvoked(); + inStatus.SetReturnInvoked(status.GetReturnVariables()); return true; } if (status.GetBreakInvoked()) { diff --git a/Source/cmWindowsRegistry.h b/Source/cmWindowsRegistry.h index 2eed297..f4a0e7b 100644 --- a/Source/cmWindowsRegistry.h +++ b/Source/cmWindowsRegistry.h @@ -2,6 +2,8 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include "cmConfigure.h" // IWYU pragma: keep + #include <cstdint> // IWYU pragma: keep #include <string> #include <vector> diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index adc500a..e727d22 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -67,9 +67,14 @@ void cmXCodeScheme::WriteXCodeXCScheme(std::ostream& fout, xout.Attribute("LastUpgradeVersion", WriteVersionString()); xout.Attribute("version", "1.3"); + cmValue propDftCfg = + Target->GetTarget()->GetProperty("XCODE_SCHEME_LAUNCH_CONFIGURATION"); + std::string launchConfiguration = + !propDftCfg.IsEmpty() ? *propDftCfg : "Debug"; + WriteBuildAction(xout, container); WriteTestAction(xout, FindConfiguration("Debug"), container); - WriteLaunchAction(xout, FindConfiguration("Debug"), container); + WriteLaunchAction(xout, FindConfiguration(launchConfiguration), container); WriteProfileAction(xout, FindConfiguration("Release")); WriteAnalyzeAction(xout, FindConfiguration("Debug")); WriteArchiveAction(xout, FindConfiguration("Release")); @@ -147,7 +152,15 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, "Xcode.DebuggerFoundation.Debugger.LLDB"); xout.Attribute("selectedLauncherIdentifier", "Xcode.DebuggerFoundation.Launcher.LLDB"); - xout.Attribute("launchStyle", "0"); + { + cmValue launchMode = + this->Target->GetTarget()->GetProperty("XCODE_SCHEME_LAUNCH_MODE"); + std::string value = "0"; // == 'AUTO' + if (launchMode && *launchMode == "WAIT") { + value = "1"; + } + xout.Attribute("launchStyle", value); + } WriteCustomWorkingDirectory(xout, configuration); xout.Attribute("ignoresPersistentStateOnLaunch", "NO"); @@ -190,6 +203,23 @@ void cmXCodeScheme::WriteLaunchAction(cmXMLWriter& xout, WriteLaunchActionAttribute(xout, "enableUBSanitizer", "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER"); + + if (cmValue value = this->Target->GetTarget()->GetProperty( + "XCODE_SCHEME_ENABLE_GPU_API_VALIDATION")) { + if (value.IsOff()) { + xout.Attribute("enableGPUValidationMode", + "1"); // unset means YES, "1" means NO + } + } + + if (cmValue value = this->Target->GetTarget()->GetProperty( + "XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION")) { + if (value.IsOn()) { + xout.Attribute("enableGPUShaderValidationMode", + "2"); // unset means NO, "2" means YES + } + } + WriteLaunchActionAttribute( xout, "stopOnEveryUBSanitizerIssue", "XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP"); diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 1c1cab3..67a8e01 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3,6 +3,7 @@ #include "cmake.h" #include <algorithm> +#include <array> #include <cstdio> #include <cstdlib> #include <cstring> @@ -22,6 +23,10 @@ #include <cmext/algorithm> #include <cmext/string_view> +#if !defined(CMAKE_BOOTSTRAP) && !defined(_WIN32) +# include <unistd.h> +#endif + #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" @@ -55,6 +60,7 @@ #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" +#include "cmUVProcessChain.h" #include "cmUtils.hxx" #include "cmVersionConfig.h" #include "cmWorkingDirectory.h" @@ -62,6 +68,7 @@ #if !defined(CMAKE_BOOTSTRAP) # include <unordered_map> +# include <cm3p/curl/curl.h> # include <cm3p/json/writer.h> # include "cmFileAPI.h" @@ -81,7 +88,6 @@ # include "cmGlobalBorlandMakefileGenerator.h" # include "cmGlobalJOMMakefileGenerator.h" # include "cmGlobalNMakeMakefileGenerator.h" -# include "cmGlobalVisualStudio10Generator.h" # include "cmGlobalVisualStudio11Generator.h" # include "cmGlobalVisualStudio12Generator.h" # include "cmGlobalVisualStudio14Generator.h" @@ -251,6 +257,8 @@ Json::Value cmake::ReportCapabilitiesJson() const std::vector<cmake::GeneratorInfo> generatorInfoList; this->GetRegisteredGenerators(generatorInfoList); + auto* curlVersion = curl_version_info(CURLVERSION_FIRST); + JsonValueMapType generatorMap; for (cmake::GeneratorInfo const& gi : generatorInfoList) { if (gi.isAlias) { // skip aliases, they are there for compatibility reasons @@ -285,6 +293,7 @@ Json::Value cmake::ReportCapabilitiesJson() const obj["generators"] = generators; obj["fileApi"] = cmFileAPI::ReportCapabilities(); obj["serverMode"] = false; + obj["tls"] = static_cast<bool>(curlVersion->features & CURL_VERSION_SSL); return obj; } @@ -777,6 +786,8 @@ enum class ListPresets Configure, Build, Test, + Package, + Workflow, All, }; } @@ -951,7 +962,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) CommandArgument::Values::One, [](std::string const& value, cmake* state) -> bool { const auto logLevel = StringToLogLevel(value); - if (logLevel == LogLevel::LOG_UNDEFINED) { + if (logLevel == Message::LogLevel::LOG_UNDEFINED) { cmSystemTools::Error( "Invalid level specified for --log-level"); return false; @@ -967,7 +978,7 @@ void cmake::SetArgs(const std::vector<std::string>& args) CommandArgument::Values::One, [](std::string const& value, cmake* state) -> bool { const auto logLevel = StringToLogLevel(value); - if (logLevel == LogLevel::LOG_UNDEFINED) { + if (logLevel == Message::LogLevel::LOG_UNDEFINED) { cmSystemTools::Error( "Invalid level specified for --loglevel"); return false; @@ -1132,12 +1143,16 @@ void cmake::SetArgs(const std::vector<std::string>& args) listPresets = ListPresets::Build; } else if (value == "test") { listPresets = ListPresets::Test; + } else if (value == "package") { + listPresets = ListPresets::Package; + } else if (value == "workflow") { + listPresets = ListPresets::Workflow; } else if (value == "all") { listPresets = ListPresets::All; } else { cmSystemTools::Error( "Invalid value specified for --list-presets.\n" - "Valid values are configure, build, test, or all. " + "Valid values are configure, build, test, package, or all. " "When no value is passed the default is configure."); return false; } @@ -1282,9 +1297,13 @@ void cmake::SetArgs(const std::vector<std::string>& args) cmCMakePresetsGraph presetsGraph; auto result = presetsGraph.ReadProjectPresets(this->GetHomeDirectory()); if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) { - cmSystemTools::Error( + std::string errorMsg = cmStrCat("Could not read presets from ", this->GetHomeDirectory(), - ": ", cmCMakePresetsGraph::ResultToString(result))); + ": ", cmCMakePresetsGraph::ResultToString(result)); + if (!presetsGraph.errors.empty()) { + errorMsg = cmStrCat(errorMsg, "\nErrors:\n", presetsGraph.errors); + } + cmSystemTools::Error(errorMsg); return; } @@ -1295,6 +1314,10 @@ void cmake::SetArgs(const std::vector<std::string>& args) presetsGraph.PrintBuildPresetList(); } else if (listPresets == ListPresets::Test) { presetsGraph.PrintTestPresetList(); + } else if (listPresets == ListPresets::Package) { + presetsGraph.PrintPackagePresetList(); + } else if (listPresets == ListPresets::Workflow) { + presetsGraph.PrintWorkflowPresetList(); } else if (listPresets == ListPresets::All) { presetsGraph.PrintAllPresets(); } @@ -1398,23 +1421,52 @@ void cmake::SetArgs(const std::vector<std::string>& args) #endif } -cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr) -{ - using LevelsPair = std::pair<std::string, LogLevel>; - static const std::vector<LevelsPair> levels = { - { "error", LogLevel::LOG_ERROR }, { "warning", LogLevel::LOG_WARNING }, - { "notice", LogLevel::LOG_NOTICE }, { "status", LogLevel::LOG_STATUS }, - { "verbose", LogLevel::LOG_VERBOSE }, { "debug", LogLevel::LOG_DEBUG }, - { "trace", LogLevel::LOG_TRACE } +namespace { +using LevelsPair = std::pair<cm::string_view, Message::LogLevel>; +using LevelsPairArray = std::array<LevelsPair, 7>; +const LevelsPairArray& getStringToLogLevelPairs() +{ + static const LevelsPairArray levels = { + { { "error", Message::LogLevel::LOG_ERROR }, + { "warning", Message::LogLevel::LOG_WARNING }, + { "notice", Message::LogLevel::LOG_NOTICE }, + { "status", Message::LogLevel::LOG_STATUS }, + { "verbose", Message::LogLevel::LOG_VERBOSE }, + { "debug", Message::LogLevel::LOG_DEBUG }, + { "trace", Message::LogLevel::LOG_TRACE } } }; + return levels; +} +} // namespace - const auto levelStrLowCase = cmSystemTools::LowerCase(levelStr); +Message::LogLevel cmake::StringToLogLevel(cm::string_view levelStr) +{ + const LevelsPairArray& levels = getStringToLogLevelPairs(); + + const auto levelStrLowCase = + cmSystemTools::LowerCase(std::string{ levelStr }); + // NOLINTNEXTLINE(readability-qualified-auto) const auto it = std::find_if(levels.cbegin(), levels.cend(), [&levelStrLowCase](const LevelsPair& p) { return p.first == levelStrLowCase; }); - return (it != levels.cend()) ? it->second : LogLevel::LOG_UNDEFINED; + return (it != levels.cend()) ? it->second : Message::LogLevel::LOG_UNDEFINED; +} + +std::string cmake::LogLevelToString(Message::LogLevel level) +{ + const LevelsPairArray& levels = getStringToLogLevelPairs(); + + // NOLINTNEXTLINE(readability-qualified-auto) + const auto it = + std::find_if(levels.cbegin(), levels.cend(), + [&level](const LevelsPair& p) { return p.second == level; }); + const cm::string_view levelStrLowerCase = + (it != levels.cend()) ? it->first : "undefined"; + std::string levelStrUpperCase = + cmSystemTools::UpperCase(std::string{ levelStrLowerCase }); + return levelStrUpperCase; } cmake::TraceFormat cmake::StringToTraceFormat(const std::string& traceStr) @@ -2096,6 +2148,9 @@ int cmake::ActualConfigure() this->UpdateConversionPathTable(); this->CleanupCommandsAndMacros(); + cmSystemTools::RemoveADirectory(this->GetHomeOutputDirectory() + + "/CMakeFiles/CMakeScratch"); + int res = this->DoPreConfigureChecks(); if (res < 0) { return -2; @@ -2319,7 +2374,6 @@ std::unique_ptr<cmGlobalGenerator> cmake::EvaluateDefaultGlobalGenerator() { "14.0", "Visual Studio 14 2015" }, // { "12.0", "Visual Studio 12 2013" }, // { "11.0", "Visual Studio 11 2012" }, // - { "10.0", "Visual Studio 10 2010" }, // { "9.0", "Visual Studio 9 2008" } }; static const char* const vsEntries[] = { @@ -2648,7 +2702,6 @@ void cmake::AddDefaultGenerators() this->Generators.push_back(cmGlobalVisualStudio14Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio12Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio11Generator::NewFactory()); - this->Generators.push_back(cmGlobalVisualStudio10Generator::NewFactory()); this->Generators.push_back(cmGlobalVisualStudio9Generator::NewFactory()); this->Generators.push_back(cmGlobalBorlandMakefileGenerator::NewFactory()); this->Generators.push_back(cmGlobalNMakeMakefileGenerator::NewFactory()); @@ -3619,6 +3672,210 @@ bool cmake::Open(const std::string& dir, bool dryRun) return gen->Open(dir, *cachedProjectName, dryRun); } +#if !defined(CMAKE_BOOTSTRAP) +template <typename T> +const T* cmake::FindPresetForWorkflow( + cm::static_string_view type, + const std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets, + const cmCMakePresetsGraph::WorkflowPreset::WorkflowStep& step) +{ + auto it = presets.find(step.PresetName); + if (it == presets.end()) { + cmSystemTools::Error(cmStrCat("No such ", type, " preset in ", + this->GetHomeDirectory(), ": \"", + step.PresetName, '"')); + return nullptr; + } + + if (it->second.Unexpanded.Hidden) { + cmSystemTools::Error(cmStrCat("Cannot use hidden ", type, " preset in ", + this->GetHomeDirectory(), ": \"", + step.PresetName, '"')); + return nullptr; + } + + if (!it->second.Expanded) { + cmSystemTools::Error(cmStrCat("Could not evaluate ", type, " preset \"", + step.PresetName, + "\": Invalid macro expansion")); + return nullptr; + } + + if (!it->second.Expanded->ConditionResult) { + cmSystemTools::Error(cmStrCat("Cannot use disabled ", type, " preset in ", + this->GetHomeDirectory(), ": \"", + step.PresetName, '"')); + return nullptr; + } + + return &*it->second.Expanded; +} + +std::function<int()> cmake::BuildWorkflowStep( + const std::vector<std::string>& args) +{ + cmUVProcessChainBuilder builder; + builder + .AddCommand(args) +# ifdef _WIN32 + .SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, _fileno(stdout)) + .SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, _fileno(stderr)); +# else + .SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, STDOUT_FILENO) + .SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, STDERR_FILENO); +# endif + return [builder]() -> int { + auto chain = builder.Start(); + chain.Wait(); + return static_cast<int>(chain.GetStatus().front()->ExitStatus); + }; +} +#endif + +int cmake::Workflow(const std::string& presetName, bool listPresets) +{ +#ifndef CMAKE_BOOTSTRAP + this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory()); + this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory()); + + cmCMakePresetsGraph settingsFile; + auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory()); + if (result != cmCMakePresetsGraph::ReadFileResult::READ_OK) { + cmSystemTools::Error( + cmStrCat("Could not read presets from ", this->GetHomeDirectory(), ": ", + cmCMakePresetsGraph::ResultToString(result))); + return 1; + } + + if (listPresets) { + settingsFile.PrintWorkflowPresetList(); + return 0; + } + + auto presetPair = settingsFile.WorkflowPresets.find(presetName); + if (presetPair == settingsFile.WorkflowPresets.end()) { + cmSystemTools::Error(cmStrCat("No such workflow preset in ", + this->GetHomeDirectory(), ": \"", presetName, + '"')); + settingsFile.PrintWorkflowPresetList(); + return 1; + } + + if (presetPair->second.Unexpanded.Hidden) { + cmSystemTools::Error(cmStrCat("Cannot use hidden workflow preset in ", + this->GetHomeDirectory(), ": \"", presetName, + '"')); + settingsFile.PrintWorkflowPresetList(); + return 1; + } + + auto const& expandedPreset = presetPair->second.Expanded; + if (!expandedPreset) { + cmSystemTools::Error(cmStrCat("Could not evaluate workflow preset \"", + presetName, "\": Invalid macro expansion")); + settingsFile.PrintWorkflowPresetList(); + return 1; + } + + if (!expandedPreset->ConditionResult) { + cmSystemTools::Error(cmStrCat("Cannot use disabled workflow preset in ", + this->GetHomeDirectory(), ": \"", presetName, + '"')); + settingsFile.PrintWorkflowPresetList(); + return 1; + } + + struct CalculatedStep + { + int StepNumber; + cm::static_string_view Type; + std::string Name; + std::function<int()> Action; + + CalculatedStep(int stepNumber, cm::static_string_view type, + std::string name, std::function<int()> action) + : StepNumber(stepNumber) + , Type(type) + , Name(std::move(name)) + , Action(std::move(action)) + { + } + }; + + std::vector<CalculatedStep> steps; + steps.reserve(expandedPreset->Steps.size()); + int stepNumber = 1; + for (auto const& step : expandedPreset->Steps) { + switch (step.PresetType) { + case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type:: + Configure: { + auto const* configurePreset = this->FindPresetForWorkflow( + "configure"_s, settingsFile.ConfigurePresets, step); + if (!configurePreset) { + return 1; + } + steps.emplace_back( + stepNumber, "configure"_s, step.PresetName, + this->BuildWorkflowStep({ cmSystemTools::GetCMakeCommand(), + "--preset", step.PresetName })); + } break; + case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::Build: { + auto const* buildPreset = this->FindPresetForWorkflow( + "build"_s, settingsFile.BuildPresets, step); + if (!buildPreset) { + return 1; + } + steps.emplace_back( + stepNumber, "build"_s, step.PresetName, + this->BuildWorkflowStep({ cmSystemTools::GetCMakeCommand(), + "--build", "--preset", step.PresetName })); + } break; + case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::Test: { + auto const* testPreset = this->FindPresetForWorkflow( + "test"_s, settingsFile.TestPresets, step); + if (!testPreset) { + return 1; + } + steps.emplace_back( + stepNumber, "test"_s, step.PresetName, + this->BuildWorkflowStep({ cmSystemTools::GetCTestCommand(), + "--preset", step.PresetName })); + } break; + case cmCMakePresetsGraph::WorkflowPreset::WorkflowStep::Type::Package: { + auto const* packagePreset = this->FindPresetForWorkflow( + "package"_s, settingsFile.PackagePresets, step); + if (!packagePreset) { + return 1; + } + steps.emplace_back( + stepNumber, "package"_s, step.PresetName, + this->BuildWorkflowStep({ cmSystemTools::GetCPackCommand(), + "--preset", step.PresetName })); + } break; + } + stepNumber++; + } + + int stepResult; + bool first = true; + for (auto const& step : steps) { + if (!first) { + std::cout << "\n"; + } + std::cout << "Executing workflow step " << step.StepNumber << " of " + << steps.size() << ": " << step.Type << " preset \"" << step.Name + << "\"\n\n" + << std::flush; + if ((stepResult = step.Action()) != 0) { + return stepResult; + } + first = false; + } +#endif + + return 0; +} + void cmake::WatchUnusedCli(const std::string& var) { #ifndef CMAKE_BOOTSTRAP diff --git a/Source/cmake.h b/Source/cmake.h index 3c6af17..54d0bb5 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -16,6 +16,7 @@ #include <vector> #include <cm/string_view> +#include <cmext/string_view> #include "cmGeneratedFileStream.h" #include "cmInstalledFile.h" @@ -119,19 +120,6 @@ public: FIND_PACKAGE_MODE }; - /** \brief Define log level constants. */ - enum LogLevel - { - LOG_UNDEFINED, - LOG_ERROR, - LOG_WARNING, - LOG_NOTICE, - LOG_STATUS, - LOG_VERBOSE, - LOG_DEBUG, - LOG_TRACE - }; - /** \brief Define supported trace formats **/ enum TraceFormat { @@ -469,9 +457,10 @@ public: bool WasLogLevelSetViaCLI() const { return this->LogLevelWasSetViaCLI; } //! Get the selected log level for `message()` commands during the cmake run. - LogLevel GetLogLevel() const { return this->MessageLogLevel; } - void SetLogLevel(LogLevel level) { this->MessageLogLevel = level; } - static LogLevel StringToLogLevel(const std::string& levelStr); + Message::LogLevel GetLogLevel() const { return this->MessageLogLevel; } + void SetLogLevel(Message::LogLevel level) { this->MessageLogLevel = level; } + static Message::LogLevel StringToLogLevel(cm::string_view levelStr); + static std::string LogLevelToString(Message::LogLevel level); static TraceFormat StringToTraceFormat(const std::string& levelStr); bool HasCheckInProgress() const @@ -612,6 +601,9 @@ public: //! run the --open option bool Open(const std::string& dir, bool dryRun); + //! run the --workflow option + int Workflow(const std::string& presetName, bool listPresets); + void UnwatchUnusedCli(const std::string& var); void WatchUnusedCli(const std::string& var); @@ -732,7 +724,7 @@ private: std::set<std::string> DebugFindPkgs; std::set<std::string> DebugFindVars; - LogLevel MessageLogLevel = LogLevel::LOG_STATUS; + Message::LogLevel MessageLogLevel = Message::LogLevel::LOG_STATUS; bool LogLevelWasSetViaCLI = false; bool LogContext = false; @@ -752,6 +744,16 @@ private: void AppendExtraGeneratorsDocumentation(std::vector<cmDocumentationEntry>&); #if !defined(CMAKE_BOOTSTRAP) + template <typename T> + const T* FindPresetForWorkflow( + cm::static_string_view type, + const std::map<std::string, cmCMakePresetsGraph::PresetPair<T>>& presets, + const cmCMakePresetsGraph::WorkflowPreset::WorkflowStep& step); + + std::function<int()> BuildWorkflowStep(const std::vector<std::string>& args); +#endif + +#if !defined(CMAKE_BOOTSTRAP) std::unique_ptr<cmMakefileProfilingData> ProfilingOutput; #endif }; @@ -873,6 +875,7 @@ private: F(cxx_std_17) \ F(cxx_std_20) \ F(cxx_std_23) \ + F(cxx_std_26) \ FOR_EACH_CXX98_FEATURE(F) \ FOR_EACH_CXX11_FEATURE(F) \ FOR_EACH_CXX14_FEATURE(F) @@ -883,7 +886,8 @@ private: F(cuda_std_14) \ F(cuda_std_17) \ F(cuda_std_20) \ - F(cuda_std_23) + F(cuda_std_23) \ + F(cuda_std_26) #define FOR_EACH_HIP_FEATURE(F) \ F(hip_std_98) \ @@ -891,4 +895,5 @@ private: F(hip_std_14) \ F(hip_std_17) \ F(hip_std_20) \ - F(hip_std_23) + F(hip_std_23) \ + F(hip_std_26) diff --git a/Source/cmake.version.manifest b/Source/cmake.version.manifest index e7010c9..79e3d19 100644 --- a/Source/cmake.version.manifest +++ b/Source/cmake.version.manifest @@ -1,6 +1,6 @@ <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" - xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" > + xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" > <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- Windows Vista --> diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index f931e9d..b754b72 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -71,7 +71,7 @@ const char* cmDocumentationUsageNote[][2] = { const char* cmDocumentationOptions[][2] = { CMAKE_STANDARD_OPTIONS_TABLE, { "--preset <preset>,--preset=<preset>", "Specify a configure preset." }, - { "--list-presets", "List available presets." }, + { "--list-presets[=<type>]", "List available presets." }, { "-E", "CMake command mode." }, { "-L[A][H]", "List non-advanced cached variables." }, { "--fresh", @@ -82,9 +82,9 @@ const char* cmDocumentationOptions[][2] = { { "-N", "View mode only." }, { "-P <file>", "Process script mode." }, { "--find-package", "Legacy pkg-config like mode. Do not use." }, - { "--graphviz=[file]", - "Generate graphviz of dependencies, see " - "CMakeGraphVizOptions.cmake for more." }, + { "--graphviz=<file>", + "Generate graphviz of dependencies, see CMakeGraphVizOptions.cmake for " + "more." }, { "--system-information [file]", "Dump information about this system." }, { "--log-level=<ERROR|WARNING|NOTICE|STATUS|VERBOSE|DEBUG|TRACE>", "Set the verbosity of messages from CMake files. " @@ -109,8 +109,7 @@ const char* cmDocumentationOptions[][2] = { { "--warn-uninitialized", "Warn about uninitialized values." }, { "--no-warn-unused-cli", "Don't warn about command line options." }, { "--check-system-vars", - "Find problems with variable usage in system " - "files." }, + "Find problems with variable usage in system files." }, { "--compile-no-warning-as-error", "Ignore COMPILE_WARNING_AS_ERROR property and " "CMAKE_COMPILE_WARNING_AS_ERROR variable." }, @@ -616,7 +615,7 @@ int do_build(int ac, char const* const* av) " <dir> = Project binary directory to be built.\n" " --preset <preset>, --preset=<preset>\n" " = Specify a build preset.\n" - " --list-presets\n" + " --list-presets[=<type>]\n" " = List available build presets.\n" " --parallel [<jobs>], -j [<jobs>]\n" " = Build in parallel using the given number of jobs. \n" @@ -627,14 +626,14 @@ int do_build(int ac, char const* const* av) " specifies a default parallel level when this " "option\n" " is not given.\n" - " --target <tgt>..., -t <tgt>... \n" + " -t <tgt>..., --target <tgt>...\n" " = Build <tgt> instead of default targets.\n" " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" " --clean-first = Build target 'clean' first, then build.\n" " (To clean only, use --target 'clean'.)\n" " --resolve-package-references={on|only|off}\n" " = Restore/resolve package references during build.\n" - " --verbose, -v = Enable verbose output - if supported - including\n" + " -v, --verbose = Enable verbose output - if supported - including\n" " the build commands to be executed. \n" " -- = Pass remaining options to the native tool.\n" ; @@ -912,6 +911,68 @@ int do_install(int ac, char const* const* av) #endif } +int do_workflow(int ac, char const* const* av) +{ +#ifdef CMAKE_BOOTSTRAP + std::cerr << "This cmake does not support --workflow\n"; + return -1; +#else + std::string presetName; + bool listPresets = false; + + using CommandArgument = + cmCommandLineArgument<bool(std::string const& value)>; + + std::vector<CommandArgument> arguments = { + CommandArgument{ "--preset", CommandArgument::Values::One, + CommandArgument::setToValue(presetName) }, + CommandArgument{ "--list-presets", CommandArgument::Values::Zero, + CommandArgument::setToTrue(listPresets) } + }; + + std::vector<std::string> inputArgs; + + inputArgs.reserve(ac - 2); + cm::append(inputArgs, av + 2, av + ac); + + decltype(inputArgs.size()) i = 0; + for (; i < inputArgs.size(); ++i) { + std::string const& arg = inputArgs[i]; + bool matched = false; + bool parsed = false; + for (auto const& m : arguments) { + matched = m.matches(arg); + if (matched) { + parsed = m.parse(arg, i, inputArgs); + break; + } + } + if (!(matched && parsed)) { + if (!matched) { + std::cerr << "Unknown argument " << arg << std::endl; + } + break; + } + } + + if (presetName.empty() && !listPresets) { + std::cerr << "TODO: Usage\n"; + return 1; + } + + cmake cm(cmake::RoleInternal, cmState::Project); + cmSystemTools::SetMessageCallback( + [&cm](const std::string& msg, const cmMessageMetadata& md) { + cmakemainMessageCallback(msg, md, &cm); + }); + cm.SetProgressCallback([&cm](const std::string& msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); + + return cm.Workflow(presetName, listPresets); +#endif +} + int do_open(int ac, char const* const* av) { #ifdef CMAKE_BOOTSTRAP @@ -981,6 +1042,9 @@ int main(int ac, char const* const* av) if (strcmp(av[1], "--open") == 0) { return do_open(ac, av); } + if (strcmp(av[1], "--workflow") == 0) { + return do_workflow(ac, av); + } if (strcmp(av[1], "-E") == 0) { return do_command(ac, av, std::move(consoleBuf)); } diff --git a/Source/cmcldeps.cxx b/Source/cmcldeps.cxx index 8921aa0..69eb19e 100644 --- a/Source/cmcldeps.cxx +++ b/Source/cmcldeps.cxx @@ -273,6 +273,7 @@ int main() std::string clrest = rest; // rc: /fo x.dir\x.rc.res -> cl: /out:x.dir\x.rc.res.dep.obj clrest = replace(clrest, "/fo ", "/out:"); + clrest = replace(clrest, "-fo ", "-out:"); clrest = replace(clrest, objfile, objfile + ".dep.obj "); cl = "\"" + cl + "\" /P /DRC_INVOKED /TC "; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 9ab39f1..67394f9 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -360,17 +360,29 @@ int HandleIWYU(const std::string& runCmd, const std::string& /* sourceFile */, int HandleTidy(const std::string& runCmd, const std::string& sourceFile, const std::vector<std::string>& orig_cmd) { - // Construct the clang-tidy command line by taking what was given - // and adding our compiler command line. The clang-tidy tool will - // automatically skip over the compiler itself and extract the - // options. - int ret; std::vector<std::string> tidy_cmd = cmExpandedList(runCmd, true); tidy_cmd.push_back(sourceFile); - tidy_cmd.emplace_back("--"); - cm::append(tidy_cmd, orig_cmd); + + // clang-tidy supports working out the compile commands from a + // compile_commands.json file in a directory given by a "-p" option, or by + // passing the compiler command line arguments after --. When the latter + // strategy is used and the build is using a compiler other than the system + // default, clang-tidy may erroneously use the system default compiler's + // headers instead of those from the custom compiler. It doesn't do that if + // given a compile_commands.json to work with instead, so prefer to use the + // compile_commands.json file when "-p" is present. + if (!cm::contains(tidy_cmd.cbegin(), tidy_cmd.cend() - 1, "-p")) { + // Construct the clang-tidy command line by taking what was given + // and adding our compiler command line. The clang-tidy tool will + // automatically skip over the compiler itself and extract the + // options. If the compiler is a custom compiler, clang-tidy might + // not correctly handle that with this approach. + tidy_cmd.emplace_back("--"); + cm::append(tidy_cmd, orig_cmd); + } // Run the tidy command line. Capture its stdout and hide its stderr. + int ret; std::string stdOut; std::string stdErr; if (!cmSystemTools::RunSingleCommand(tidy_cmd, &stdOut, &stdErr, &ret, @@ -791,6 +803,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, } if (args[1] == "env") { +#ifndef CMAKE_BOOTSTRAP + cmSystemTools::EnvDiff env; +#endif + auto ai = args.cbegin() + 2; auto ae = args.cend(); for (; ai != ae; ++ai) { @@ -803,16 +819,40 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, } if (cmHasLiteralPrefix(a, "--unset=")) { // Unset environment variable. +#ifdef CMAKE_BOOTSTRAP cmSystemTools::UnPutEnv(a.substr(8)); +#else + env.UnPutEnv(a.substr(8)); +#endif + } else if (a == "--modify") { +#ifdef CMAKE_BOOTSTRAP + std::cerr + << "cmake -E env: --modify not available during bootstrapping\n"; + return 1; +#else + if (++ai == ae) { + std::cerr << "cmake -E env: --modify missing a parameter\n"; + return 1; + } + std::string const& op = *ai; + if (!env.ParseOperation(op)) { + std::cerr << "cmake -E env: invalid parameter to --modify: " << op + << '\n'; + return 1; + } +#endif } else if (!a.empty() && a[0] == '-') { // Environment variable and command names cannot start in '-', // so this must be an unknown option. - std::cerr << "cmake -E env: unknown option '" << a << '\'' - << std::endl; + std::cerr << "cmake -E env: unknown option '" << a << "'\n"; return 1; } else if (a.find('=') != std::string::npos) { // Set environment variable. +#ifdef CMAKE_BOOTSTRAP cmSystemTools::PutEnv(a); +#else + env.PutEnv(a); +#endif } else { // This is the beginning of the command. break; @@ -820,10 +860,14 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, } if (ai == ae) { - std::cerr << "cmake -E env: no command given" << std::endl; + std::cerr << "cmake -E env: no command given\n"; return 1; } +#ifndef CMAKE_BOOTSTRAP + env.ApplyToCurrentEnv(); +#endif + // Execute command from remaining arguments. std::vector<std::string> cmd(ai, ae); int retval; @@ -1668,16 +1712,15 @@ cmsys::Status cmcmd::SymlinkInternal(std::string const& file, } std::string linktext = cmSystemTools::GetFilenameName(file); #if defined(_WIN32) && !defined(__CYGWIN__) - std::string errorMessage; - cmsys::Status status = - cmSystemTools::CreateSymlink(linktext, link, &errorMessage); + cmsys::Status status = cmSystemTools::CreateSymlinkQuietly(linktext, link); // Creating a symlink will fail with ERROR_PRIVILEGE_NOT_HELD if the user // does not have SeCreateSymbolicLinkPrivilege, or if developer mode is not // active. In that case, we try to copy the file. if (status.GetWindows() == ERROR_PRIVILEGE_NOT_HELD) { status = cmSystemTools::CopyFileAlways(file, link); } else if (!status) { - cmSystemTools::Error(errorMessage); + cmSystemTools::Error(cmStrCat("failed to create symbolic link '", link, + "': ", status.GetString())); } return status; #else @@ -2242,13 +2285,18 @@ bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg, // Parse the link command to extract information we need. for (; arg != argEnd; ++arg) { if (cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL:YES") == 0 || - cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL") == 0) { + cmSystemTools::Strucmp(arg->c_str(), "-INCREMENTAL:YES") == 0 || + cmSystemTools::Strucmp(arg->c_str(), "/INCREMENTAL") == 0 || + cmSystemTools::Strucmp(arg->c_str(), "-INCREMENTAL") == 0) { this->Incremental = true; - } else if (cmSystemTools::Strucmp(arg->c_str(), "/MANIFEST:NO") == 0) { + } else if (cmSystemTools::Strucmp(arg->c_str(), "/MANIFEST:NO") == 0 || + cmSystemTools::Strucmp(arg->c_str(), "-MANIFEST:NO") == 0) { this->LinkGeneratesManifest = false; - } else if (cmHasLiteralPrefix(*arg, "/Fe")) { + } else if (cmHasLiteralPrefix(*arg, "/Fe") || + cmHasLiteralPrefix(*arg, "-Fe")) { this->TargetFile = arg->substr(3); - } else if (cmHasLiteralPrefix(*arg, "/out:")) { + } else if (cmHasLiteralPrefix(*arg, "/out:") || + cmHasLiteralPrefix(*arg, "-out:")) { this->TargetFile = arg->substr(5); } } diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx index d520c14..f239576 100644 --- a/Source/kwsys/Directory.cxx +++ b/Source/kwsys/Directory.cxx @@ -43,12 +43,12 @@ public: { std::string Name; #if defined(_WIN32) && !defined(__CYGWIN__) - _wfinddata_t FindData; + WIN32_FIND_DATAW FindData; #endif FileData(std::string name #if defined(_WIN32) && !defined(__CYGWIN__) , - _wfinddata_t data + WIN32_FIND_DATAW data #endif ) : Name(std::move(name)) @@ -115,8 +115,8 @@ std::string Directory::GetFilePath(std::size_t i) const bool Directory::FileIsDirectory(std::size_t i) const { #if defined(_WIN32) && !defined(__CYGWIN__) - _wfinddata_t const& data = this->Internal->Files[i].FindData; - return (data.attrib & FILE_ATTRIBUTE_DIRECTORY) != 0; + auto const& data = this->Internal->Files[i].FindData; + return (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; #else std::string const& path = this->GetFilePath(i); return kwsys::SystemTools::FileIsDirectory(path); @@ -127,9 +127,9 @@ bool Directory::FileIsSymlink(std::size_t i) const { std::string const& path = this->GetFilePath(i); #if defined(_WIN32) && !defined(__CYGWIN__) - _wfinddata_t const& data = this->Internal->Files[i].FindData; + auto const& data = this->Internal->Files[i].FindData; return kwsys::SystemTools::FileIsSymlinkWithAttr( - Encoding::ToWindowsExtendedPath(path), data.attrib); + Encoding::ToWindowsExtendedPath(path), data.dwFileAttributes); #else return kwsys::SystemTools::FileIsSymlink(path); #endif @@ -157,7 +157,7 @@ namespace KWSYS_NAMESPACE { Status Directory::Load(std::string const& name, std::string* errorMessage) { this->Clear(); - intptr_t srchHandle; + HANDLE srchHandle; char* buf; size_t bufLength; size_t n = name.size(); @@ -176,14 +176,14 @@ Status Directory::Load(std::string const& name, std::string* errorMessage) snprintf(buf, bufLength, "%s/*", name.c_str()); } } - struct _wfinddata_t data; // data of current file + WIN32_FIND_DATAW data; // data of current file // Now put them into the file array srchHandle = - _wfindfirst((wchar_t*)Encoding::ToWindowsExtendedPath(buf).c_str(), &data); + FindFirstFileW(Encoding::ToWindowsExtendedPath(buf).c_str(), &data); delete[] buf; - if (srchHandle == -1) { + if (srchHandle == INVALID_HANDLE_VALUE) { Status status = Status::POSIX_errno(); if (errorMessage) { *errorMessage = status.GetString(); @@ -193,10 +193,11 @@ Status Directory::Load(std::string const& name, std::string* errorMessage) // Loop through names do { - this->Internal->Files.emplace_back(Encoding::ToNarrow(data.name), data); - } while (_wfindnext(srchHandle, &data) != -1); + this->Internal->Files.emplace_back(Encoding::ToNarrow(data.cFileName), + data); + } while (FindNextFileW(srchHandle, &data)); this->Internal->Path = name; - if (_findclose(srchHandle) == -1) { + if (!FindClose(srchHandle)) { Status status = Status::POSIX_errno(); if (errorMessage) { *errorMessage = status.GetString(); @@ -209,7 +210,7 @@ Status Directory::Load(std::string const& name, std::string* errorMessage) unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, std::string* errorMessage) { - intptr_t srchHandle; + HANDLE srchHandle; char* buf; size_t bufLength; size_t n = name.size(); @@ -222,13 +223,13 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, buf = new char[n + 2 + 1]; snprintf(buf, bufLength, "%s/*", name.c_str()); } - struct _wfinddata_t data; // data of current file + WIN32_FIND_DATAW data; // data of current file // Now put them into the file array - srchHandle = _wfindfirst((wchar_t*)Encoding::ToWide(buf).c_str(), &data); + srchHandle = FindFirstFileW(Encoding::ToWide(buf).c_str(), &data); delete[] buf; - if (srchHandle == -1) { + if (srchHandle == INVALID_HANDLE_VALUE) { if (errorMessage) { if (unsigned int errorId = GetLastError()) { LPSTR message = nullptr; @@ -250,8 +251,8 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, unsigned long count = 0; do { count++; - } while (_wfindnext(srchHandle, &data) != -1); - _findclose(srchHandle); + } while (FindNextFileW(srchHandle, &data)); + FindClose(srchHandle); return count; } diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 5889a4b..a20901c 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -536,9 +536,11 @@ public: StringMap TranslationMap; #endif #ifdef _WIN32 - static std::string GetCasePathName(std::string const& pathIn); + static std::string GetCasePathName(std::string const& pathIn, + bool const cache); static std::string GetActualCaseForPathCached(std::string const& path); static const char* GetEnvBuffered(const char* key); + std::map<std::string, std::string, SystemToolsPathCaseCmp> FindFileMap; std::map<std::string, std::string, SystemToolsPathCaseCmp> PathCaseMap; std::map<std::string, std::string> EnvMap; #endif @@ -571,7 +573,8 @@ public: static SystemToolsStatic* SystemToolsStatics; #ifdef _WIN32 -std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn) +std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn, + bool const cache) { std::string casePath; @@ -623,14 +626,31 @@ std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn) } else { std::string test_str = casePath; test_str += path_components[idx]; - WIN32_FIND_DATAW findData; - HANDLE hFind = - ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData); - if (INVALID_HANDLE_VALUE != hFind) { - path_components[idx] = Encoding::ToNarrow(findData.cFileName); - ::FindClose(hFind); - } else { - converting = false; + + bool found_in_cache = false; + if (cache) { + auto const it = SystemToolsStatics->FindFileMap.find(test_str); + if (it != SystemToolsStatics->FindFileMap.end()) { + path_components[idx] = it->second; + found_in_cache = true; + } + } + + if (!found_in_cache) { + WIN32_FIND_DATAW findData; + HANDLE hFind = + ::FindFirstFileW(Encoding::ToWide(test_str).c_str(), &findData); + if (INVALID_HANDLE_VALUE != hFind) { + auto case_file_name = Encoding::ToNarrow(findData.cFileName); + if (cache) { + SystemToolsStatics->FindFileMap.emplace(test_str, + case_file_name); + } + path_components[idx] = std::move(case_file_name); + ::FindClose(hFind); + } else { + converting = false; + } } } } @@ -642,19 +662,16 @@ std::string SystemToolsStatic::GetCasePathName(std::string const& pathIn) std::string SystemToolsStatic::GetActualCaseForPathCached(std::string const& p) { - // Check to see if actual case has already been called - // for this path, and the result is stored in the PathCaseMap - auto& pcm = SystemToolsStatics->PathCaseMap; - { - auto itr = pcm.find(p); - if (itr != pcm.end()) { - return itr->second; - } - } - std::string casePath = SystemToolsStatic::GetCasePathName(p); - if (casePath.size() <= MAX_PATH) { - pcm[p] = casePath; + std::string casePath; + + auto it = SystemToolsStatics->PathCaseMap.find(p); + if (it != SystemToolsStatics->PathCaseMap.end()) { + casePath = it->second; + } else { + casePath = SystemToolsStatic::GetCasePathName(p, true); + SystemToolsStatics->PathCaseMap.emplace(p, casePath); } + return casePath; } #endif @@ -3067,17 +3084,14 @@ std::string SystemTools::GetRealPath(const std::string& path, return ret; } -bool SystemTools::FileIsDirectory(const std::string& inName) +// Remove any trailing slash from the name except in a root component. +static const char* RemoveTrailingSlashes( + const std::string& inName, char (&local_buffer)[KWSYS_SYSTEMTOOLS_MAXPATH], + std::string& string_buffer) { - if (inName.empty()) { - return false; - } size_t length = inName.size(); const char* name = inName.c_str(); - // Remove any trailing slash from the name except in a root component. - char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; - std::string string_buffer; size_t last = length - 1; if (last > 0 && (name[last] == '/' || name[last] == '\\') && strcmp(name, "/") != 0 && name[last - 1] != ':') { @@ -3091,6 +3105,19 @@ bool SystemTools::FileIsDirectory(const std::string& inName) } } + return name; +} + +bool SystemTools::FileIsDirectory(const std::string& inName) +{ + if (inName.empty()) { + return false; + } + + char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; + std::string string_buffer; + const auto name = RemoveTrailingSlashes(inName, local_buffer, string_buffer); + // Now check the file node type. #if defined(_WIN32) DWORD attr = @@ -3107,9 +3134,21 @@ bool SystemTools::FileIsDirectory(const std::string& inName) } } -bool SystemTools::FileIsExecutable(const std::string& name) +bool SystemTools::FileIsExecutable(const std::string& inName) { - return !FileIsDirectory(name) && TestFileAccess(name, TEST_FILE_EXECUTE); +#ifdef _WIN32 + char local_buffer[KWSYS_SYSTEMTOOLS_MAXPATH]; + std::string string_buffer; + const auto name = RemoveTrailingSlashes(inName, local_buffer, string_buffer); + const auto attr = + GetFileAttributesW(Encoding::ToWindowsExtendedPath(name).c_str()); + + // On Windows any file that exists and is not a directory is considered + // readable and therefore also executable: + return attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY); +#else + return !FileIsDirectory(inName) && TestFileAccess(inName, TEST_FILE_EXECUTE); +#endif } #if defined(_WIN32) @@ -3655,7 +3694,7 @@ std::string SystemTools::RelativePath(const std::string& local, std::string SystemTools::GetActualCaseForPath(const std::string& p) { #ifdef _WIN32 - return SystemToolsStatic::GetCasePathName(p); + return SystemToolsStatic::GetCasePathName(p, false); #else return p; #endif diff --git a/Templates/MSBuild/FlagTables/v10_Cuda.json b/Templates/MSBuild/FlagTables/v10_Cuda.json index b3230ac..b0765f5 100644 --- a/Templates/MSBuild/FlagTables/v10_Cuda.json +++ b/Templates/MSBuild/FlagTables/v10_Cuda.json @@ -70,118 +70,6 @@ ] }, { - "name": "cmake-temp-gencode", - "switch": "gencode=", - "comment": "", - "value": "", - "flags": [ - "UserValue", - "SemicolonAppendable" - ] - }, - { - "name": "cmake-temp-gencode", - "switch": "gencode", - "comment": "", - "value": "", - "flags": [ - "UserFollowing", - "SemicolonAppendable" - ] - }, - { - "name": "cmake-temp-gencode", - "switch": "-generate-code=", - "comment": "", - "value": "", - "flags": [ - "UserValue", - "SemicolonAppendable" - ] - }, - { - "name": "cmake-temp-gencode", - "switch": "-generate-code", - "comment": "", - "value": "", - "flags": [ - "UserFollowing", - "SemicolonAppendable" - ] - }, - { - "name": "cmake-temp-code", - "switch": "code=", - "comment": "", - "value": "", - "flags": [ - "UserValue" - ] - }, - { - "name": "cmake-temp-code", - "switch": "code", - "comment": "", - "value": "", - "flags": [ - "UserFollowing" - ] - }, - { - "name": "cmake-temp-code", - "switch": "-gpu-code=", - "comment": "", - "value": "", - "flags": [ - "UserValue" - ] - }, - { - "name": "cmake-temp-code", - "switch": "-gpu-code", - "comment": "", - "value": "", - "flags": [ - "UserFollowing" - ] - }, - { - "name": "cmake-temp-arch", - "switch": "arch=", - "comment": "", - "value": "", - "flags": [ - "UserValue" - ] - }, - { - "name": "cmake-temp-arch", - "switch": "arch", - "comment": "", - "value": "", - "flags": [ - "UserFollowing" - ] - }, - { - "name": "cmake-temp-arch", - "switch": "-gpu-architecture=", - "comment": "", - "value": "", - "flags": [ - "UserValue" - ] - }, - { - "name": "cmake-temp-arch", - "switch": "-gpu-architecture", - "comment": "", - "value": "", - "flags": [ - "UserFollowing" - ] - }, - { "name": "FastMath", "switch": "use_fast_math", "comment": "", diff --git a/Tests/Assembler/CMakeLists.txt b/Tests/Assembler/CMakeLists.txt index 1b7e57d..8f6b355 100644 --- a/Tests/Assembler/CMakeLists.txt +++ b/Tests/Assembler/CMakeLists.txt @@ -24,6 +24,12 @@ if("${CMAKE_GENERATOR}" MATCHES "Makefile|Xcode|Ninja" AND elseif("${CMAKE_SYSTEM_NAME};${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "Darwin;arm64") list(APPEND C_FLAGS -arch arm64) endif() + if(CMAKE_C_COMPILER_ID STREQUAL "Clang") + # Just in case the user is passing -flto, we need to pass -fno-lto to + # clang when generating the assembly file, or else clang will generate + # LLVM IR instead of assembly. + list(APPEND C_FLAGS -fno-lto) + endif() # Clang on OS X, and perhaps other compilers, do not support -g # for both generating and assembling, so drop it from generating. list(REMOVE_ITEM C_FLAGS -g) diff --git a/Tests/CMakeLib/CMakeLists.txt b/Tests/CMakeLib/CMakeLists.txt index 1d45162..612d4b4 100644 --- a/Tests/CMakeLib/CMakeLists.txt +++ b/Tests/CMakeLib/CMakeLists.txt @@ -47,12 +47,10 @@ if(WIN32) list(APPEND CMakeLib_TESTS testVisualStudioSlnParser.cxx ) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testVisualStudioSlnParser.h.in - ${CMAKE_CURRENT_BINARY_DIR}/testVisualStudioSlnParser.h @ONLY) + configure_file(testVisualStudioSlnParser.h.in testVisualStudioSlnParser.h @ONLY) endif() -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testXMLParser.h.in - ${CMAKE_CURRENT_BINARY_DIR}/testXMLParser.h @ONLY) +configure_file(testXMLParser.h.in testXMLParser.h @ONLY) create_test_sourcelist(CMakeLib_TEST_SRCS CMakeLibTests.cxx ${CMakeLib_TESTS}) add_executable(CMakeLibTests ${CMakeLib_TEST_SRCS}) diff --git a/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt b/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt index 4bef6c5..b4bc921 100644 --- a/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt +++ b/Tests/CMakeLib/PseudoMemcheck/CMakeLists.txt @@ -1,6 +1,6 @@ -foreach (_retval 0 1) - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/memtester.cxx.in" "${CMAKE_CURRENT_BINARY_DIR}/ret${_retval}.cxx" @ONLY) -endforeach () +foreach(_retval IN ITEMS 0 1) + configure_file(memtester.cxx.in ret${_retval}.cxx @ONLY) +endforeach() include_directories(${CMake_SOURCE_DIR}/Source ${CMake_BINARY_DIR}/Source) diff --git a/Tests/CMakeLib/testArgumentParser.cxx b/Tests/CMakeLib/testArgumentParser.cxx index 965690c..e044794 100644 --- a/Tests/CMakeLib/testArgumentParser.cxx +++ b/Tests/CMakeLib/testArgumentParser.cxx @@ -1,57 +1,182 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ +#include <functional> #include <initializer_list> #include <iostream> +#include <map> #include <string> +#include <utility> #include <vector> +#include <cm/optional> #include <cm/string_view> #include <cmext/string_view> #include "cmArgumentParser.h" +#include "cmArgumentParserTypes.h" namespace { -struct Result +struct Result : public ArgumentParser::ParseResult { bool Option1 = false; bool Option2 = false; std::string String1; - std::string String2; + cm::optional<std::string> String2; + cm::optional<std::string> String3; + ArgumentParser::Maybe<std::string> String4; + ArgumentParser::NonEmpty<std::string> String5; + ArgumentParser::NonEmpty<std::string> String6; - std::vector<std::string> List1; - std::vector<std::string> List2; - std::vector<std::string> List3; + ArgumentParser::NonEmpty<std::vector<std::string>> List1; + ArgumentParser::NonEmpty<std::vector<std::string>> List2; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> List3; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> List4; + cm::optional<ArgumentParser::NonEmpty<std::vector<std::string>>> List5; + cm::optional<ArgumentParser::MaybeEmpty<std::vector<std::string>>> List6; std::vector<std::vector<std::string>> Multi1; std::vector<std::vector<std::string>> Multi2; - std::vector<std::vector<std::string>> Multi3; + cm::optional<std::vector<std::vector<std::string>>> Multi3; + cm::optional<std::vector<std::vector<std::string>>> Multi4; + + cm::optional<std::string> Pos0; + cm::optional<std::string> Pos1; + cm::optional<std::string> Pos2; + + bool Func0_ = false; + ArgumentParser::Continue Func0(cm::string_view) + { + Func0_ = true; + return ArgumentParser::Continue::No; + } + + std::string Func1_; + ArgumentParser::Continue Func1(cm::string_view arg) + { + Func1_ = std::string(arg); + return ArgumentParser::Continue::No; + } + + std::map<std::string, std::vector<std::string>> Func2_; + ArgumentParser::Continue Func2(cm::string_view key, cm::string_view arg) + { + Func2_[std::string(key)].emplace_back(arg); + return key == "FUNC_2b" ? ArgumentParser::Continue::Yes + : ArgumentParser::Continue::No; + } + + std::vector<std::string> Func3_; + ArgumentParser::Continue Func3(cm::string_view arg) + { + Func3_.emplace_back(arg); + return ArgumentParser::Continue::Yes; + } + + std::map<std::string, std::vector<std::string>> Func4_; + ArgumentParser::Continue Func4(cm::string_view key, cm::string_view arg) + { + Func4_[std::string(key)].emplace_back(arg); + return key == "FUNC_4b" ? ArgumentParser::Continue::Yes + : ArgumentParser::Continue::No; + } + + ArgumentParser::Maybe<std::string> UnboundMaybe{ 'u', 'n', 'b', 'o', + 'u', 'n', 'd' }; + ArgumentParser::MaybeEmpty<std::vector<std::string>> UnboundMaybeEmpty{ + 1, "unbound" + }; + ArgumentParser::NonEmpty<std::vector<std::string>> UnboundNonEmpty{ + 1, "unbound" + }; + ArgumentParser::NonEmpty<std::string> UnboundNonEmptyStr{ 'u', 'n', 'b', 'o', + 'u', 'n', 'd' }; + + std::vector<cm::string_view> ParsedKeywords; }; std::initializer_list<cm::string_view> const args = { /* clang-format off */ + "pos0", // position index 0 "OPTION_1", // option + "pos2", // position index 2, ignored because after keyword + // "OPTION_2", // option that is not present "STRING_1", // string arg missing value - "STRING_2", "foo", "bar", // string arg + unparsed value + "STRING_2", "foo", "bar", // string arg + unparsed value, presence captured + // "STRING_3", // string arg that is not present + "STRING_4", // string arg allowed to be missing value + "STRING_5", "foo", // string arg that is not empty + "STRING_6", "", // string arg that is empty "LIST_1", // list arg missing values "LIST_2", "foo", "bar", // list arg with 2 elems "LIST_3", "bar", // list arg ... "LIST_3", "foo", // ... with continuation + "LIST_4", // list arg missing values, presence captured + // "LIST_5", // list arg that is not present + "LIST_6", // list arg allowed to be empty "MULTI_2", // multi list with 0 lists "MULTI_3", "foo", "bar", // multi list with first list with two elems "MULTI_3", "bar", "foo", // multi list with second list with two elems + // "MULTI_4", // multi list arg that is not present + "FUNC_0", // callback arg missing value + "FUNC_1", "foo", "ign1", // callback with one arg + unparsed value + "FUNC_2a", "foo", "ign2", // callback with keyword-dependent arg count + "FUNC_2b", "bar", "zot", // callback with keyword-dependent arg count + "FUNC_3", "foo", "bar", // callback with list arg ... + "FUNC_4a", "foo", "ign4", // callback with keyword-dependent arg count + "FUNC_4b", "bar", "zot", // callback with keyword-dependent arg count /* clang-format on */ }; bool verifyResult(Result const& result, - std::vector<std::string> const& unparsedArguments, - std::vector<std::string> const& keywordsMissingValue) + std::vector<std::string> const& unparsedArguments) { static std::vector<std::string> const foobar = { "foo", "bar" }; static std::vector<std::string> const barfoo = { "bar", "foo" }; - static std::vector<std::string> const missing = { "STRING_1", "LIST_1" }; + static std::vector<std::string> const unbound = { "unbound" }; + static std::vector<cm::string_view> const parsedKeywords = { + /* clang-format off */ + "OPTION_1", + "STRING_1", + "STRING_2", + "STRING_4", + "STRING_5", + "STRING_6", + "LIST_1", + "LIST_2", + "LIST_3", + "LIST_3", + "LIST_4", + "LIST_6", + "MULTI_2", + "MULTI_3", + "MULTI_3", + "FUNC_0", + "FUNC_1", + "FUNC_2a", + "FUNC_2b", + "FUNC_3", + "FUNC_4a", + "FUNC_4b", + /* clang-format on */ + }; + static std::map<std::string, std::vector<std::string>> const func2map = { + { "FUNC_2a", { "foo" } }, { "FUNC_2b", { "bar", "zot" } } + }; + static std::map<std::string, std::vector<std::string>> const func4map = { + { "FUNC_4a", { "foo" } }, { "FUNC_4b", { "bar", "zot" } } + }; + static std::map<cm::string_view, std::string> const keywordErrors = { + { "STRING_1"_s, " missing required value\n" }, + { "STRING_6"_s, " empty string not allowed\n" }, + { "LIST_1"_s, " missing required value\n" }, + { "LIST_4"_s, " missing required value\n" }, + { "FUNC_0"_s, " missing required value\n" } + }; + static std::vector<std::string> const unparsed = { "pos2", "bar", "ign1", + "ign2", "ign4" }; #define ASSERT_TRUE(x) \ do { \ @@ -61,26 +186,63 @@ bool verifyResult(Result const& result, } \ } while (false) + ASSERT_TRUE(!result); + ASSERT_TRUE(result.Option1); ASSERT_TRUE(!result.Option2); ASSERT_TRUE(result.String1.empty()); - ASSERT_TRUE(result.String2 == "foo"); + ASSERT_TRUE(result.String2); + ASSERT_TRUE(*result.String2 == "foo"); + ASSERT_TRUE(!result.String3); + ASSERT_TRUE(result.String4.empty()); + ASSERT_TRUE(result.String5 == "foo"); + ASSERT_TRUE(result.String6.empty()); ASSERT_TRUE(result.List1.empty()); ASSERT_TRUE(result.List2 == foobar); - ASSERT_TRUE(result.List3 == barfoo); + ASSERT_TRUE(result.List3); + ASSERT_TRUE(*result.List3 == barfoo); + ASSERT_TRUE(result.List4); + ASSERT_TRUE(result.List4->empty()); + ASSERT_TRUE(!result.List5); + ASSERT_TRUE(result.List6); + ASSERT_TRUE(result.List6->empty()); ASSERT_TRUE(result.Multi1.empty()); ASSERT_TRUE(result.Multi2.size() == 1); ASSERT_TRUE(result.Multi2[0].empty()); - ASSERT_TRUE(result.Multi3.size() == 2); - ASSERT_TRUE(result.Multi3[0] == foobar); - ASSERT_TRUE(result.Multi3[1] == barfoo); + ASSERT_TRUE(result.Multi3); + ASSERT_TRUE((*result.Multi3).size() == 2); + ASSERT_TRUE((*result.Multi3)[0] == foobar); + ASSERT_TRUE((*result.Multi3)[1] == barfoo); + ASSERT_TRUE(!result.Multi4); + + ASSERT_TRUE(result.Pos0 == "pos0"); + ASSERT_TRUE(!result.Pos1); + ASSERT_TRUE(!result.Pos2); + + ASSERT_TRUE(result.Func0_ == false); + ASSERT_TRUE(result.Func1_ == "foo"); + ASSERT_TRUE(result.Func2_ == func2map); + ASSERT_TRUE(result.Func3_ == foobar); + ASSERT_TRUE(result.Func4_ == func4map); + + ASSERT_TRUE(unparsedArguments == unparsed); - ASSERT_TRUE(unparsedArguments.size() == 1); - ASSERT_TRUE(unparsedArguments[0] == "bar"); - ASSERT_TRUE(keywordsMissingValue == missing); + ASSERT_TRUE(result.UnboundMaybe == "unbound"); + ASSERT_TRUE(result.UnboundMaybeEmpty == unbound); + ASSERT_TRUE(result.UnboundNonEmpty == unbound); + ASSERT_TRUE(result.UnboundNonEmptyStr == "unbound"); + + ASSERT_TRUE(result.ParsedKeywords == parsedKeywords); + + ASSERT_TRUE(result.GetKeywordErrors().size() == keywordErrors.size()); + for (auto const& ke : result.GetKeywordErrors()) { + auto const ki = keywordErrors.find(ke.first); + ASSERT_TRUE(ki != keywordErrors.end()); + ASSERT_TRUE(ke.second == ki->second); + } return true; } @@ -89,45 +251,116 @@ bool testArgumentParserDynamic() { Result result; std::vector<std::string> unparsedArguments; - std::vector<std::string> keywordsMissingValue; - - cmArgumentParser<void>{} - .Bind("OPTION_1"_s, result.Option1) - .Bind("OPTION_2"_s, result.Option2) - .Bind("STRING_1"_s, result.String1) - .Bind("STRING_2"_s, result.String2) - .Bind("LIST_1"_s, result.List1) - .Bind("LIST_2"_s, result.List2) - .Bind("LIST_3"_s, result.List3) - .Bind("MULTI_1"_s, result.Multi1) - .Bind("MULTI_2"_s, result.Multi2) - .Bind("MULTI_3"_s, result.Multi3) - .Parse(args, &unparsedArguments, &keywordsMissingValue); - - return verifyResult(result, unparsedArguments, keywordsMissingValue); + + std::function<ArgumentParser::Continue(cm::string_view, cm::string_view)> + func4 = [&result](cm::string_view key, + cm::string_view arg) -> ArgumentParser::Continue { + return result.Func4(key, arg); + }; + + static_cast<ArgumentParser::ParseResult&>(result) = + cmArgumentParser<void>{} + .Bind(0, result.Pos0) + .Bind(1, result.Pos1) + .Bind(2, result.Pos2) + .Bind("OPTION_1"_s, result.Option1) + .Bind("OPTION_2"_s, result.Option2) + .Bind("STRING_1"_s, result.String1) + .Bind("STRING_2"_s, result.String2) + .Bind("STRING_3"_s, result.String3) + .Bind("STRING_4"_s, result.String4) + .Bind("STRING_5"_s, result.String5) + .Bind("STRING_6"_s, result.String6) + .Bind("LIST_1"_s, result.List1) + .Bind("LIST_2"_s, result.List2) + .Bind("LIST_3"_s, result.List3) + .Bind("LIST_4"_s, result.List4) + .Bind("LIST_5"_s, result.List5) + .Bind("LIST_6"_s, result.List6) + .Bind("MULTI_1"_s, result.Multi1) + .Bind("MULTI_2"_s, result.Multi2) + .Bind("MULTI_3"_s, result.Multi3) + .Bind("MULTI_4"_s, result.Multi4) + .Bind("FUNC_0"_s, + [&result](cm::string_view arg) -> ArgumentParser::Continue { + return result.Func0(arg); + }) + .Bind("FUNC_1"_s, + [&result](cm::string_view arg) -> ArgumentParser::Continue { + return result.Func1(arg); + }) + .Bind("FUNC_2a"_s, + [&result](cm::string_view key, cm::string_view arg) + -> ArgumentParser::Continue { return result.Func2(key, arg); }) + .Bind("FUNC_2b"_s, + [&result](cm::string_view key, cm::string_view arg) + -> ArgumentParser::Continue { return result.Func2(key, arg); }) + .Bind("FUNC_3"_s, + [&result](cm::string_view arg) -> ArgumentParser::Continue { + return result.Func3(arg); + }) + .Bind("FUNC_4a"_s, func4) + .Bind("FUNC_4b"_s, func4) + .BindParsedKeywords(result.ParsedKeywords) + .Parse(args, &unparsedArguments); + + return verifyResult(result, unparsedArguments); } +static auto const parserStaticFunc4 = + [](Result& result, cm::string_view key, + cm::string_view arg) -> ArgumentParser::Continue { + return result.Func4(key, arg); +}; +static auto const parserStatic = // + cmArgumentParser<Result>{} + .Bind(0, &Result::Pos0) + .Bind(1, &Result::Pos1) + .Bind(2, &Result::Pos2) + .Bind("OPTION_1"_s, &Result::Option1) + .Bind("OPTION_2"_s, &Result::Option2) + .Bind("STRING_1"_s, &Result::String1) + .Bind("STRING_2"_s, &Result::String2) + .Bind("STRING_3"_s, &Result::String3) + .Bind("STRING_4"_s, &Result::String4) + .Bind("STRING_5"_s, &Result::String5) + .Bind("STRING_6"_s, &Result::String6) + .Bind("LIST_1"_s, &Result::List1) + .Bind("LIST_2"_s, &Result::List2) + .Bind("LIST_3"_s, &Result::List3) + .Bind("LIST_4"_s, &Result::List4) + .Bind("LIST_5"_s, &Result::List5) + .Bind("LIST_6"_s, &Result::List6) + .Bind("MULTI_1"_s, &Result::Multi1) + .Bind("MULTI_2"_s, &Result::Multi2) + .Bind("MULTI_3"_s, &Result::Multi3) + .Bind("MULTI_4"_s, &Result::Multi4) + .Bind("FUNC_0"_s, &Result::Func0) + .Bind("FUNC_1"_s, &Result::Func1) + .Bind("FUNC_2a"_s, &Result::Func2) + .Bind("FUNC_2b"_s, &Result::Func2) + .Bind("FUNC_3"_s, + [](Result& result, cm::string_view arg) -> ArgumentParser::Continue { + return result.Func3(arg); + }) + .Bind("FUNC_4a"_s, parserStaticFunc4) + .Bind("FUNC_4b"_s, parserStaticFunc4) + .BindParsedKeywords(&Result::ParsedKeywords) + /* keep semicolon on own line */; + bool testArgumentParserStatic() { - static auto const parser = // - cmArgumentParser<Result>{} - .Bind("OPTION_1"_s, &Result::Option1) - .Bind("OPTION_2"_s, &Result::Option2) - .Bind("STRING_1"_s, &Result::String1) - .Bind("STRING_2"_s, &Result::String2) - .Bind("LIST_1"_s, &Result::List1) - .Bind("LIST_2"_s, &Result::List2) - .Bind("LIST_3"_s, &Result::List3) - .Bind("MULTI_1"_s, &Result::Multi1) - .Bind("MULTI_2"_s, &Result::Multi2) - .Bind("MULTI_3"_s, &Result::Multi3); - std::vector<std::string> unparsedArguments; - std::vector<std::string> keywordsMissingValue; - Result const result = - parser.Parse(args, &unparsedArguments, &keywordsMissingValue); + Result const result = parserStatic.Parse(args, &unparsedArguments); + return verifyResult(result, unparsedArguments); +} - return verifyResult(result, unparsedArguments, keywordsMissingValue); +bool testArgumentParserStaticBool() +{ + std::vector<std::string> unparsedArguments; + Result result; + ASSERT_TRUE(parserStatic.Parse(result, args, &unparsedArguments) == false); + return verifyResult(result, unparsedArguments); } } // namespace @@ -144,5 +377,10 @@ int testArgumentParser(int /*unused*/, char* /*unused*/ []) return -1; } + if (!testArgumentParserStaticBool()) { + std::cout << "While executing testArgumentParserStaticBool().\n"; + return -1; + } + return 0; } diff --git a/Tests/CMakeLib/testCMExtEnumSet.cxx b/Tests/CMakeLib/testCMExtEnumSet.cxx index 64c437b..dbb0a54 100644 --- a/Tests/CMakeLib/testCMExtEnumSet.cxx +++ b/Tests/CMakeLib/testCMExtEnumSet.cxx @@ -191,6 +191,15 @@ void testEdition() ++failed; } } + { + cm::enum_set<Test> testSet1; + cm::enum_set<Test> testSet2{ Test::A, Test::C, Test::B }; + + testSet1 = { Test::A, Test::C, Test::B }; + if (testSet1.size() != 3 || testSet1 != testSet2) { + ++failed; + } + } } } diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 3e400c2..6e35df9 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -40,10 +40,10 @@ set(ENV{HOME} \"${TEST_HOME}\") endif() # Suppress generator deprecation warnings in test suite. -if(CMAKE_GENERATOR MATCHES "^Visual Studio 10 2010") - set(TEST_WARN_VS10_CODE "set(ENV{CMAKE_WARN_VS10} OFF)") +if(CMAKE_GENERATOR MATCHES "^Visual Studio 11 2012") + set(TEST_WARN_VS11_CODE "set(ENV{CMAKE_WARN_VS11} OFF)") else() - set(TEST_WARN_VS10_CODE "") + set(TEST_WARN_VS11_CODE "") endif() # 3.9 or later provides a definitive answer to whether we are multi-config @@ -89,7 +89,7 @@ if(BUILD_TESTING) endif() endif() - set(MAKE_IS_GNU ) + set(MAKE_IS_GNU) if(CMAKE_MAKE_PROGRAM MATCHES make) execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} no_such_target --version RESULT_VARIABLE res OUTPUT_VARIABLE out ERROR_VARIABLE out) @@ -101,7 +101,7 @@ if(BUILD_TESTING) endif() # some old versions of make simply cannot handle spaces in paths - if (MAKE_IS_GNU OR + if(MAKE_IS_GNU OR CMAKE_MAKE_PROGRAM MATCHES "nmake|gmake|wmake" OR CMAKE_GENERATOR MATCHES "Visual Studio|Xcode|Borland|Ninja") set(MAKE_SUPPORTS_SPACES 1) @@ -181,7 +181,7 @@ if(BUILD_TESTING) ERROR_VARIABLE my_err) string(REGEX REPLACE "HKEY_LOCAL_MACHINE\\\\SOFTWARE\\\\Wow6432Node\\\\Microsoft\\\\Windows CE Tools\\\\SDKs\\\\" ";" sdk_list "${sdk_reg}") list(LENGTH sdk_list sdk_list_len) - if (${sdk_list_len} GREATER 1) + if(${sdk_list_len} GREATER 1) list(GET sdk_list 1 _sdk) # The first entry is always empty due to the regex replace above string(STRIP ${_sdk} _sdk) # Make sure there is no newline in the SDK name endif() @@ -205,7 +205,7 @@ if(BUILD_TESTING) select_wince_sdk(reg_wince wince_sdk) set(reg_tegra "[HKEY_LOCAL_MACHINE\\SOFTWARE\\NVIDIA Corporation\\Nsight Tegra;sdkRoot]") set(reg_nasm "[HKEY_CURRENT_USER\\SOFTWARE\\nasm]") - foreach(reg vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra nasm) + foreach(reg IN ITEMS vs10 vs11 vs12 vs14 ws80 ws81 ws10_0 wp80 wp81 wince tegra nasm) get_filename_component(r "${reg_${reg}}" ABSOLUTE) if(IS_DIRECTORY "${r}" AND NOT "${r}" STREQUAL "/registry") set(${reg} 1) @@ -227,7 +227,7 @@ if(BUILD_TESTING) set(vs_versions vs15) endif() endif() - foreach(info ${vs_versions}) + foreach(info IN LISTS vs_versions) cmake_host_system_information(RESULT found QUERY "${info_${info}}") if(found) set(${info} 1) @@ -287,12 +287,12 @@ if(BUILD_TESTING) "Should the long tests be run (such as Bootstrap)." ON) mark_as_advanced(CMAKE_RUN_LONG_TESTS) - if (CMAKE_RUN_LONG_TESTS) + if(CMAKE_RUN_LONG_TESTS) option(CTEST_TEST_CTEST "Should the tests that run a full sub ctest process be run?" OFF) mark_as_advanced(CTEST_TEST_CTEST) - endif () + endif() option(CTEST_TEST_CPACK "Should the tests that use '--build-target package' be run?" @@ -367,9 +367,9 @@ if(BUILD_TESTING) if(CMake_TEST_RESOURCES) ADD_TEST_MACRO(VSResource VSResource) - if (CMAKE_GENERATOR MATCHES "Ninja") + if(CMAKE_GENERATOR MATCHES "Ninja") add_test_macro(VSResourceNinjaForceRSP VSResourceNinjaForceRSP) - endif () + endif() endif() if(_isMultiConfig) set(MSManifest_CTEST_OPTIONS -C $<CONFIGURATION>) @@ -394,6 +394,9 @@ if(BUILD_TESTING) if(CMake_TEST_XCODE_SWIFT) ADD_TEST_MACRO(SwiftMix SwiftMix) endif() + if(CMAKE_Swift_COMPILER_VERSION VERSION_GREATER_EQUAL 5.1) + ADD_TEST_MACRO(SwiftMixLib Swifty) + endif() endif() if(CMAKE_Fortran_COMPILER) ADD_TEST_MACRO(FortranOnly FortranOnly) @@ -431,7 +434,7 @@ if(BUILD_TESTING) if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|[9][0-9])") ADD_TEST_MACRO(CSharpOnly CSharpOnly) - if(NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") + if(NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64") ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx) ADD_TEST_MACRO(CSharpLinkFromCxx CSharpLinkFromCxx) endif() @@ -499,7 +502,7 @@ if(BUILD_TESTING) endif() ADD_TEST_MACRO(SourcesProperty SourcesProperty) ADD_TEST_MACRO(SourceFileProperty SourceFileProperty) - if (NOT CMAKE_GENERATOR STREQUAL "Xcode") + if(NOT CMAKE_GENERATOR STREQUAL "Xcode") ADD_TEST_MACRO(SourceFileIncludeDirProperty SourceFileIncludeDirProperty) endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "LCC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" @@ -618,6 +621,11 @@ if(BUILD_TESTING) set(Module.CheckIPOSupported-CXX_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_CXX=${CMake_TEST_IPO_WORKS_CXX}) ADD_TEST_MACRO(Module.CheckIPOSupported-CXX CheckIPOSupported-CXX) + if(CMake_TEST_CUDA) + ADD_TEST_MACRO(Module.CheckIPOSupported-CUDA CheckIPOSupported-CUDA) + set_property(TEST Module.CheckIPOSupported-CUDA APPEND PROPERTY LABELS "CUDA") + endif() + if(CMAKE_Fortran_COMPILER) set(Module.CheckIPOSupported-Fortran_BUILD_OPTIONS -DCMake_TEST_IPO_WORKS_Fortran=${CMake_TEST_IPO_WORKS_Fortran}) ADD_TEST_MACRO(Module.CheckIPOSupported-Fortran CheckIPOSupported-Fortran) @@ -641,11 +649,11 @@ if(BUILD_TESTING) ADD_TEST_MACRO(Module.WriteCompilerDetectionHeader WriteCompilerDetectionHeader) - if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "LCC") + if(APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "LCC") include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-fPIE run_pic_test) else() - if (CMAKE_CXX_COMPILER_ID MATCHES "PGI" + if(CMAKE_CXX_COMPILER_ID MATCHES "PGI" OR CMAKE_CXX_COMPILER_ID MATCHES "PathScale" OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") set(run_pic_test 0) @@ -654,7 +662,7 @@ if(BUILD_TESTING) endif() endif() - if (run_pic_test) + if(run_pic_test) ADD_TEST_MACRO(PositionIndependentTargets PositionIndependentTargets) endif() @@ -725,13 +733,15 @@ if(BUILD_TESTING) # mainly it tests that cmake doesn't crash when generating these project files. if(CMAKE_GENERATOR MATCHES "^(Unix Makefiles|Ninja)$" AND NOT "${CMAKE_CURRENT_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") - foreach(extraGenerator + foreach( + extraGenerator + IN ITEMS "CodeBlocks" "CodeLite" "Eclipse CDT4" "Kate" "Sublime Text 2" - ) + ) string(REPLACE " " "" extraGeneratorTestName "Simple_${extraGenerator}Generator") add_test(${extraGeneratorTestName} ${CMAKE_CTEST_COMMAND} --build-and-test @@ -786,7 +796,7 @@ if(BUILD_TESTING) --build-exe-dir "${CMake_BINARY_DIR}/Tests/SubProject/foo" --test-command foo ) - set_tests_properties ( SubProject-Stage2 PROPERTIES DEPENDS SubProject) + set_tests_properties(SubProject-Stage2 PROPERTIES DEPENDS SubProject) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SubProject") endif() @@ -1056,8 +1066,11 @@ if(BUILD_TESTING) endif() endif() if(NSIS_MAKENSIS_EXECUTABLE) - set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS} - -DCPACK_BINARY_NSIS:BOOL=ON) + execute_process(COMMAND ${NSIS_MAKENSIS_EXECUTABLE} "-VERSION" ERROR_QUIET OUTPUT_QUIET RESULT_VARIABLE NSIS_OK) + if("${NSIS_OK}" STREQUAL "0") + set(CPackComponents_BUILD_OPTIONS ${CPackComponents_BUILD_OPTIONS} + -DCPACK_BINARY_NSIS:BOOL=ON) + endif() endif() add_test(CPackComponents ${CMAKE_CTEST_COMMAND} @@ -1119,7 +1132,7 @@ if(BUILD_TESTING) set(CPACK_GENERATOR_STRING_${CPackGen} ${CPackGen}) endif() set(CPackRun_CPackGen "-DCPackGen=${CPACK_GENERATOR_STRING_${CPackGen}}") - foreach(CPackComponentWay ${CWAYLST}) + foreach(CPackComponentWay IN LISTS CWAYLST) set(CPackRun_CPackComponentWay "-DCPackComponentWay=${CPackComponentWay}") add_test(CPackComponentsForAll-${CPackGen}-${CPackComponentWay} ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE} @@ -1153,7 +1166,6 @@ if(BUILD_TESTING) "components-source" "components-shlibdeps1" "components-depend1" - "components-depend2" "compression") # Run additional tests if dpkg-shlibdeps is available (and is new enough version) find_program(SHLIBDEPS_EXECUTABLE NAMES dpkg-shlibdeps) @@ -1173,6 +1185,11 @@ if(BUILD_TESTING) list(APPEND DEB_CONFIGURATIONS_TO_TEST "shlibdeps-with-private-lib-failure" "shlibdeps-with-private-lib-success") endif() + # Check if distro has symbols or shlibs data + file(GLOB SHLIBS_FILES_EXIST "/var/lib/dpkg/info/*.shlibs" "/var/lib/dpkg/info/*.symbols") + if(SHLIBS_FILES_EXIST) + list(APPEND DEB_CONFIGURATIONS_TO_TEST "components-depend2") + endif() endif() set(CPackGen "DEB") @@ -1338,7 +1355,7 @@ if(BUILD_TESTING) --test-command complex) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/ComplexOneConfig") # because of the registry write these tests depend on each other - set_tests_properties ( complex PROPERTIES DEPENDS complexOneConfig) + set_tests_properties(complex PROPERTIES DEPENDS complexOneConfig) add_test(Environment ${CMAKE_CTEST_COMMAND} --build-and-test @@ -1421,62 +1438,66 @@ if(BUILD_TESTING) endif() # test for Find modules, simple cases - foreach(_mod IN ITEMS - ALSA - Boost - BLAS - BZip2 - CURL - Cups - Doxygen - DevIL - EnvModules - EXPAT - Fontconfig - Freetype - GDAL - GIF - Git - GLEW - GLUT - GnuTLS - GSL - GTK2 - Iconv - ICU - Intl - Jasper - JNI - JPEG - JsonCpp - LAPACK - LibArchive - LibLZMA - LibRHash - Libinput - LibUV - LibXml2 - LibXslt - LTTngUST - ODBC - OpenACC - OpenCL - OpenGL - OpenMP - OpenSSL - MPI - PNG - Patch - PostgreSQL - Protobuf - SDL - SQLite3 - TIFF - Vulkan - X11 - XalanC - XercesC - ) + foreach( + _mod + IN ITEMS + ALSA + BLAS + Boost + BZip2 + Cups + CURL + DevIL + Doxygen + EnvModules + EXPAT + Fontconfig + Freetype + GDAL + GIF + Git + GLEW + GLUT + GnuTLS + GSL + GTK2 + Iconv + ICU + Intl + Jasper + JNI + JPEG + JsonCpp + LAPACK + LibArchive + Libinput + LibLZMA + LibRHash + LibUV + LibXml2 + LibXslt + LTTngUST + MPI + ODBC + OpenACC + OpenAL + OpenCL + OpenGL + OpenMP + OpenSP + OpenSSL + Patch + PNG + PostgreSQL + Protobuf + SDL + SQLite3 + TIFF + Vulkan + X11 + XalanC + XercesC + ) if(CMake_TEST_Find${_mod}) add_subdirectory(Find${_mod}) endif() @@ -1522,7 +1543,7 @@ if(BUILD_TESTING) # CMake_TEST_FindMatlab_MCR_ROOT_DIR: indicates an optional root directory for the MCR, required on Linux if(CMake_TEST_FindMatlab OR CMake_TEST_FindMatlab_ROOT_DIR OR CMake_TEST_FindMatlab_MCR OR CMake_TEST_FindMatlab_MCR_ROOT_DIR) - set(FindMatlab_additional_test_options ) + set(FindMatlab_additional_test_options) if(CMake_TEST_FindMatlab_MCR OR CMake_TEST_FindMatlab_MCR_ROOT_DIR) set(FindMatlab_additional_test_options -DIS_MCR=TRUE) endif() @@ -1556,7 +1577,7 @@ if(BUILD_TESTING) endif() set(ExternalProject_BUILD_OPTIONS "") - foreach(vcs CVS SVN GIT HG) + foreach(vcs IN ITEMS CVS SVN GIT HG) if(DEFINED CMake_TEST_ExternalProject_${vcs}) list(APPEND ExternalProject_BUILD_OPTIONS -DEP_TEST_${vcs}=${CMake_TEST_ExternalProject_${vcs}}) endif() @@ -1656,7 +1677,8 @@ if(BUILD_TESTING) RUN_SERIAL 1 TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT} WORKING_DIRECTORY ${CMake_SOURCE_DIR}/Tests/ExternalProjectUpdate - DEPENDS ExternalProjectUpdateSetup ) + DEPENDS ExternalProjectUpdateSetup + ) execute_process( COMMAND ${CMAKE_COMMAND} @@ -1711,7 +1733,7 @@ if(BUILD_TESTING) function(add_tutorial_test step_name use_mymath tutorial_arg pass_regex) set(tutorial_test_name Tutorial${step_name}) set(tutorial_build_dir "${CMake_BINARY_DIR}/Tests/Tutorial/${step_name}") - if (use_mymath) + if(use_mymath) set(tutorial_build_options "") else() set(tutorial_test_name ${tutorial_test_name}_MYMATH) @@ -1735,7 +1757,7 @@ if(BUILD_TESTING) if(NOT CMake_TEST_EXTERNAL_CMAKE) foreach(STP RANGE 2 12) - if (STP EQUAL 6) + if(STP EQUAL 8) set(pass_regex ".*using log and exp") else() set(pass_regex "The square root of 25 is 5") @@ -1994,11 +2016,11 @@ if(BUILD_TESTING) --test-command Exec2 ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/LinkLineOrder") - set_tests_properties ( qtwrapping PROPERTIES DEPENDS wrapping) - set_tests_properties ( testdriver1 PROPERTIES DEPENDS qtwrapping) - set_tests_properties ( testdriver2 PROPERTIES DEPENDS testdriver1) - set_tests_properties ( testdriver3 PROPERTIES DEPENDS testdriver2) - set_tests_properties ( linkorder2 PROPERTIES DEPENDS linkorder1) + set_tests_properties(qtwrapping PROPERTIES DEPENDS wrapping) + set_tests_properties(testdriver1 PROPERTIES DEPENDS qtwrapping) + set_tests_properties(testdriver2 PROPERTIES DEPENDS testdriver1) + set_tests_properties(testdriver3 PROPERTIES DEPENDS testdriver2) + set_tests_properties(linkorder2 PROPERTIES DEPENDS linkorder1) # Test static linking on toolchains known to support it. if((CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "LCC") @@ -2030,9 +2052,9 @@ if(BUILD_TESTING) "${CMake_BINARY_DIR}/Tests/SubDirSpaces/testfromsubdir.obj" ) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SubDirSpaces") - endif () + endif() - if (WIN32) + if(WIN32) add_test(SubDir ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/SubDir" @@ -2044,7 +2066,7 @@ if(BUILD_TESTING) "${CMake_BINARY_DIR}/Tests/SubDir/ShouldBeHere" "${CMake_BINARY_DIR}/Tests/SubDir/testfromsubdir.obj" ) - else () + else() add_test(SubDir ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/SubDir" @@ -2056,7 +2078,7 @@ if(BUILD_TESTING) "${CMake_BINARY_DIR}/Tests/SubDir/ShouldBeHere" "${CMake_BINARY_DIR}/Tests/SubDir/testfromsubdir.o" ) - endif () + endif() list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/SubDir") if(MSVC OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_SIMULATE_ID STREQUAL "MSVC")) @@ -2067,6 +2089,15 @@ if(BUILD_TESTING) if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang" AND NOT CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM") ADD_TEST_MACRO(PrecompiledHeader foo) endif() + + set(MSVCDebugInformationFormat_BUILD_OPTIONS -DCMake_TEST_CUDA=${CMake_TEST_CUDA}) + if(CMAKE_Fortran_COMPILER) + list(APPEND MSVCDebugInformationFormat_BUILD_OPTIONS -DCMake_TEST_Fortran=1) + endif() + ADD_TEST_MACRO(MSVCDebugInformationFormat) + set_property(TEST MSVCDebugInformationFormat APPEND + PROPERTY LABELS "CUDA") + set(MSVCRuntimeLibrary_BUILD_OPTIONS -DCMake_TEST_CUDA=${CMake_TEST_CUDA}) ADD_TEST_MACRO(MSVCRuntimeLibrary) set_property(TEST MSVCRuntimeLibrary APPEND @@ -2080,7 +2111,7 @@ if(BUILD_TESTING) ADD_TEST_MACRO(ModuleDefinition example_exe) endif() - if (CMAKE_C_COMPILER_ID MATCHES "Watcom" AND WIN32) + if(CMAKE_C_COMPILER_ID MATCHES "Watcom" AND WIN32) ADD_TEST_MACRO(WatcomRuntimeLibrary) endif() @@ -2116,7 +2147,7 @@ if(BUILD_TESTING) if(MSVC AND NOT MSVC_VERSION LESS 1310 AND (NOT CMAKE_GENERATOR MATCHES "Visual Studio 9 " OR CMAKE_SIZEOF_VOID_P EQUAL 4) - AND (NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") + AND (NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64") ) ADD_TEST_MACRO(VSMASM VSMASM) endif() @@ -2128,7 +2159,7 @@ if(BUILD_TESTING) if(NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio 9 " AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v90" - AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") + AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64") ADD_TEST_MACRO(VSWindowsFormsResx VSWindowsFormsResx) ADD_TEST_MACRO(VSManagedCustomCommand) endif() @@ -2157,7 +2188,7 @@ if(BUILD_TESTING) # The test (and tested property) works with .sln files, so it's skipped when: # * cmake --build is set up to use MSBuild, since the MSBuild invocation does not use the .sln file set(_last_test "") - foreach(config ${CMAKE_CONFIGURATION_TYPES}) + foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES) add_test(NAME VSExcludeFromDefaultBuild-${config} COMMAND ${CMAKE_CTEST_COMMAND} --build-and-test "${CMake_SOURCE_DIR}/Tests/VSExcludeFromDefaultBuild" @@ -2295,7 +2326,7 @@ if(BUILD_TESTING) ADD_TEST_MACRO(VSNASM VSNASM) endif() - if (CMake_TEST_GreenHillsMULTI) + if(CMake_TEST_GreenHillsMULTI) macro(add_test_GhsMulti test_name test_dir bin_sub_dir build_opts) separate_arguments(_ghs_build_opts UNIX_COMMAND ${build_opts}) separate_arguments(_ghs_toolset_extra UNIX_COMMAND ${ghs_toolset_extra}) @@ -2356,7 +2387,7 @@ if(BUILD_TESTING) set(ghs_config_name "__default__") endif() # test integrity build - if (NOT ghs_skip_integrity AND (NOT ghs_target_platform OR ghs_target_platform MATCHES "integrity")) + if(NOT ghs_skip_integrity AND (NOT ghs_target_platform OR ghs_target_platform MATCHES "integrity")) add_test_GhsMulti(integrityDDInt GhsMultiIntegrity/GhsMultiIntegrityDDInt "" "") add_test_GhsMulti(integrityMonolith GhsMultiIntegrity/GhsMultiIntegrityMonolith "" "") add_test_GhsMulti(integrityDD GhsMultiIntegrity/GhsMultiIntegrityDD "" "") @@ -2412,9 +2443,6 @@ if(BUILD_TESTING) list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/VSAndroid/${name}") endmacro() if(tegra AND NOT "${CMake_SOURCE_DIR};${CMake_BINARY_DIR}" MATCHES " ") - if(vs10) - add_test_VSAndroid(vs10 "Visual Studio 10 2010" "Tegra-Android") - endif() if(vs11) add_test_VSAndroid(vs11 "Visual Studio 11 2012" "Tegra-Android") endif() @@ -2438,8 +2466,8 @@ if(BUILD_TESTING) add_test_VSAndroid(vs17 "Visual Studio 17 2022" "ARM") endif() - if (APPLE) - if (CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + if(APPLE) + if(CMAKE_COMPILER_IS_GNUCXX OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(BundleTestInstallDir "${CMake_BINARY_DIR}/Tests/BundleTest/InstallDirectory") add_test(BundleTest ${CMAKE_CTEST_COMMAND} @@ -2475,8 +2503,8 @@ if(BUILD_TESTING) add_subdirectory(ObjC) add_subdirectory(ObjCXX) - endif () - endif () + endif() + endif() if(APPLE AND CTEST_TEST_CPACK) add_test(BundleGeneratorTest ${CMAKE_CTEST_COMMAND} @@ -2667,7 +2695,10 @@ if(BUILD_TESTING) endif() if(NOT DEFINED CMake_TEST_CTestUpdate_HG AND HG_EXECUTABLE AND (UNIX OR NOT "${HG_EXECUTABLE}" MATCHES "cygwin")) - set(CMake_TEST_CTestUpdate_HG 1) + execute_process(COMMAND "${HG_EXECUTABLE}" --version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE HG_RV) + if(HG_RV EQUAL 0) + set(CMake_TEST_CTestUpdate_HG 1) + endif() endif() if(CMake_TEST_CTestUpdate_HG) if(NOT HG_EXECUTABLE) @@ -3195,24 +3226,24 @@ if(BUILD_TESTING) --output-log "${CMake_BINARY_DIR}/Tests/CTestTestFdSetSize/testOutput.log" ) - if (CMAKE_TESTS_CDASH_SERVER) + if(CMAKE_TESTS_CDASH_SERVER) set(regex "^([^:]+)://([^/]+)(.*)$") - if ("${CMAKE_TESTS_CDASH_SERVER}" MATCHES "${regex}") + if("${CMAKE_TESTS_CDASH_SERVER}" MATCHES "${regex}") set(protocol "${CMAKE_MATCH_1}") set(server "${CMAKE_MATCH_2}") set(path "${CMAKE_MATCH_3}") - else () + else() set(protocol "http") set(server "open.cdash.org") set(path "") message("warning: CMAKE_TESTS_CDASH_SERVER does not match expected regex...") message(" ...using default url='${protocol}://${server}${path}' for CTestTest[23]") - endif () - endif () + endif() + endif() - if (CTEST_TEST_CTEST AND CMAKE_RUN_LONG_TESTS AND CMAKE_TESTS_CDASH_SERVER) + if(CTEST_TEST_CTEST AND CMAKE_RUN_LONG_TESTS AND CMAKE_TESTS_CDASH_SERVER) configure_file("${CMake_SOURCE_DIR}/Tests/CTestTest/test.cmake.in" "${CMake_BINARY_DIR}/Tests/CTestTest/test.cmake" @ONLY ESCAPE_QUOTES) add_test(CTestTest ${CMAKE_CTEST_COMMAND} @@ -3254,19 +3285,19 @@ if(BUILD_TESTING) # these tests take a long time, make sure they have it # if timeouts have not already been set get_test_property(CTestTest TIMEOUT PREVIOUS_TIMEOUT) - if ("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND) - set_tests_properties ( CTestTest + if("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND) + set_tests_properties(CTestTest PROPERTIES TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT}) - endif () + endif() if(NOT CMake_TEST_EXTERNAL_CMAKE) get_test_property(CTestTest2 TIMEOUT PREVIOUS_TIMEOUT) if("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND) - set_tests_properties ( CTestTest2 + set_tests_properties(CTestTest2 PROPERTIES TIMEOUT ${CMAKE_LONG_TEST_TIMEOUT}) endif() endif() - endif () + endif() if(CMake_TEST_EXTERNAL_CMAKE) set(CMAKE_SKIP_BOOTSTRAP_TEST 1) @@ -3302,10 +3333,9 @@ if(BUILD_TESTING) # provide more time for the bootstrap test get_test_property(BootstrapTest TIMEOUT PREVIOUS_TIMEOUT) - if ("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND) - set_tests_properties ( BootstrapTest - PROPERTIES TIMEOUT 5400) - endif () + if("${PREVIOUS_TIMEOUT}" MATCHES NOTFOUND) + set_tests_properties(BootstrapTest PROPERTIES TIMEOUT 5400) + endif() endif() if(CMAKE_Fortran_COMPILER) @@ -3369,56 +3399,70 @@ if(BUILD_TESTING) set(JavaExportImport_BUILD_OPTIONS -DCMake_TEST_NESTED_MAKE_PROGRAM:FILEPATH=${CMake_TEST_EXPLICIT_MAKE_PROGRAM}) ADD_TEST_MACRO(JavaExportImport JavaExportImport) - get_filename_component(JNIPATH ${Java_JAVAC_EXECUTABLE} PATH) + get_filename_component(JAVACPATH ${Java_JAVAC_EXECUTABLE} REALPATH) + get_filename_component(JNIPATH ${JAVACPATH} PATH) find_file(JNI_H jni.h "${JNIPATH}/../include" "${JNIPATH}/../java/include") if(JNI_H AND EXISTS "${JNI_H}") # in case jni.h is a broken symlink file(READ "${JNI_H}" JNI_FILE) if("${JNI_FILE}" MATCHES "JDK1_2") - add_test(NAME Java.Jar COMMAND ${CMAKE_CTEST_COMMAND} - --build-and-test - "${CMake_SOURCE_DIR}/Tests/Java" - "${CMake_BINARY_DIR}/Tests/JavaJar" - ${build_generator_args} - --build-project hello - --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJar/" - --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>) - list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJar") - # For next tests, java tool must have same architecture as toolchain - math(EXPR _object_mode "${CMAKE_SIZEOF_VOID_P} * 8") execute_process( COMMAND "${Java_JAVA_EXECUTABLE}" -version OUTPUT_VARIABLE _version ERROR_VARIABLE _version RESULT_VARIABLE _result ) - if(_result EQUAL 0 AND _version MATCHES "${_object_mode}-Bit") - ## next test is valid only if Java version is less than 1.10 - if ("${Java_VERSION}" VERSION_LESS 1.10) - add_test(NAME Java.Javah COMMAND ${CMAKE_CTEST_COMMAND} - --build-and-test - "${CMake_SOURCE_DIR}/Tests/JavaJavah" - "${CMake_BINARY_DIR}/Tests/JavaJavah" - ${build_generator_args} - --build-project helloJavah - --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/" - --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>) - list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah") + + # E2K has broken Java RVM before 3.5.2 + if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "e2k" AND _result EQUAL 0) + string(REGEX MATCH "RVM ([0-9.]+)" RVMVER "${_version}") + # Consider empty match a broken version too + if("${CMAKE_MATCH_1}" VERSION_LESS "3.5.2") + set(BROKEN_RVM TRUE) endif() - ## next test is valid only if Java is, at least, version 1.8 - if (NOT "${Java_VERSION}" VERSION_LESS 1.8) - add_test(NAME Java.NativeHeaders COMMAND ${CMAKE_CTEST_COMMAND} - --build-and-test - "${CMake_SOURCE_DIR}/Tests/JavaNativeHeaders" - "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders" - ${build_generator_args} - --build-project helloJavaNativeHeaders - --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/" - --build-target install - --build-options - "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/Install" - --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>) - list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders") + endif() + + if(NOT BROKEN_RVM) + add_test(NAME Java.Jar COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/Java" + "${CMake_BINARY_DIR}/Tests/JavaJar" + ${build_generator_args} + --build-project hello + --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJar/" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJar") + + # For next tests, java tool must have same architecture as toolchain + math(EXPR _object_mode "${CMAKE_SIZEOF_VOID_P} * 8") + if(_result EQUAL 0 AND _version MATCHES "${_object_mode}-Bit") + ## next test is valid only if Java version is less than 1.10 + if("${Java_VERSION}" VERSION_LESS 1.10) + add_test(NAME Java.Javah COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/JavaJavah" + "${CMake_BINARY_DIR}/Tests/JavaJavah" + ${build_generator_args} + --build-project helloJavah + --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaJavah/" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaJavah") + endif() + ## next test is valid only if Java is, at least, version 1.8 + if(NOT "${Java_VERSION}" VERSION_LESS 1.8) + add_test(NAME Java.NativeHeaders COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/JavaNativeHeaders" + "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders" + ${build_generator_args} + --build-project helloJavaNativeHeaders + --build-run-dir "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/" + --build-target install + --build-options + "-DCMAKE_INSTALL_PREFIX:PATH=${CMake_BINARY_DIR}/Tests/JavaNativeHeaders/Install" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIG>) + list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/JavaNativeHeaders") + endif() endif() endif() endif() @@ -3480,18 +3524,18 @@ if(BUILD_TESTING) endif() if(CMAKE_TEST_PLPLOT_DIR) - add_test(plplot ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_PLPLOT_DIR}/../../EasyDashboardScripts/plplot.cmake ) + add_test(plplot ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_PLPLOT_DIR}/../../EasyDashboardScripts/plplot.cmake) set_tests_properties ( plplot PROPERTIES TIMEOUT 5400) endif() if(CMAKE_TEST_CHICKEN_DIR) - add_test(Chicken ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_CHICKEN_DIR}/../../EasyDashboardScripts/Chicken.cmake ) - set_tests_properties ( Chicken PROPERTIES TIMEOUT 5400) + add_test(Chicken ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_CHICKEN_DIR}/../../EasyDashboardScripts/Chicken.cmake) + set_tests_properties(Chicken PROPERTIES TIMEOUT 5400) endif() if(CMAKE_TEST_KDELIBS_ALPHA_1_DIR) - add_test(KDELibsAlpha1 ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_KDELIBS_ALPHA_1_DIR}/../../EasyDashboardScripts/kdelibs.cmake ) - set_tests_properties ( KDELibsAlpha1 PROPERTIES TIMEOUT 5400) + add_test(KDELibsAlpha1 ${CMAKE_CTEST_COMMAND} -V -S ${CMAKE_TEST_KDELIBS_ALPHA_1_DIR}/../../EasyDashboardScripts/kdelibs.cmake) + set_tests_properties(KDELibsAlpha1 PROPERTIES TIMEOUT 5400) endif() # Define a set of "contract" tests, each activated by a cache entry @@ -3501,11 +3545,7 @@ if(BUILD_TESTING) # The directory should also contain a Configure.cmake file that # sets "CMake_TEST_CONTRACT_<project>_<var>" variables to configure # the code below. - foreach(project - PLplot - Trilinos - VTK - ) + foreach(project IN ITEMS PLplot Trilinos VTK) if(CMake_TEST_CONTRACT_${project}) include(Contracts/${project}/Configure.cmake) ADD_TEST_MACRO(Contracts.${project} ${CMake_TEST_CONTRACT_${project}_RUN_TEST}) @@ -3578,6 +3618,14 @@ if(BUILD_TESTING) add_subdirectory(CMakeGUI) endif() + # Run CheckSourceTree as the very last test in the CMake/CTest/CPack test + # suite. It detects if any changes have been made to the CMake source tree + # by any previous configure, build or test steps. + if(GIT_EXECUTABLE AND EXISTS "${CMake_SOURCE_DIR}/.git" + AND NOT "${CMake_SOURCE_DIR}" STREQUAL "${CMake_BINARY_DIR}") + add_subdirectory(CheckSourceTree) + endif() + # If this is not an in-source build, provide a target to wipe out # all the test build directories. This must come at the end after # all the above logic has finished adding to TEST_BUILD_DIRS diff --git a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt index 49a4041..0907d03 100644 --- a/Tests/CMakeOnly/AllFindModules/CMakeLists.txt +++ b/Tests/CMakeOnly/AllFindModules/CMakeLists.txt @@ -56,6 +56,15 @@ macro(check_version_string MODULE_NAME VERSION_VAR) if (NOT _exclude_pos EQUAL -1) message(STATUS "excluding check of ${VERSION_VAR}='${${VERSION_VAR}}' due to local configuration") elseif (${MODULE_NAME}_FOUND) + + unset(SKIP_CHECK) + if(${MODULE_NAME} STREQUAL "HG") + execute_process(COMMAND "${HG_EXECUTABLE}" --version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE HG_RV) + if(NOT HG_RV EQUAL 0) + message(WARNING "Broken HG executable detected, skipping") + set(SKIP_CHECK TRUE) + endif() + endif() if (DEFINED ${VERSION_VAR}) message(STATUS "${VERSION_VAR}='${${VERSION_VAR}}'") if (NOT ${VERSION_VAR} MATCHES "^[0-9]") @@ -71,7 +80,9 @@ macro(check_version_string MODULE_NAME VERSION_VAR) message(SEND_ERROR "unexpected: ${VERSION_VAR} is NOT VERSION_GREATER 0") endif() else() - message(SEND_ERROR "${MODULE_NAME}_FOUND is set but version number variable ${VERSION_VAR} is NOT DEFINED") + if(NOT SKIP_CHECK) + message(SEND_ERROR "${MODULE_NAME}_FOUND is set but version number variable ${VERSION_VAR} is NOT DEFINED") + endif() endif() endif () endmacro() diff --git a/Tests/CMakeTests/CMakeLists.txt b/Tests/CMakeTests/CMakeLists.txt index 9e0b891..bd2dd7e 100644 --- a/Tests/CMakeTests/CMakeLists.txt +++ b/Tests/CMakeTests/CMakeLists.txt @@ -59,18 +59,3 @@ if(GIT_EXECUTABLE) ) AddCMakeTest(PolicyCheck "${PolicyCheck_PreArgs}") endif() - -# Run CheckSourceTree as the very last test in the CMake/CTest/CPack test -# suite. It detects if any changes have been made to the CMake source tree -# by any previous configure, build or test steps. -# -if(GIT_EXECUTABLE) - string(REPLACE "\\" "/" ENV_HOME "$ENV{HOME}") - set(CheckSourceTree_PreArgs - "-DCMake_BINARY_DIR:PATH=${CMake_BINARY_DIR}" - "-DCMake_SOURCE_DIR:PATH=${CMake_SOURCE_DIR}" - "-DGIT_EXECUTABLE:STRING=${GIT_EXECUTABLE}" - "-DHOME:STRING=${ENV_HOME}" - ) - AddCMakeTest(CheckSourceTree "${CheckSourceTree_PreArgs}") -endif() diff --git a/Tests/CMakeTests/CheckSourceTreeTest.cmake.in b/Tests/CMakeTests/CheckSourceTreeTest.cmake.in deleted file mode 100644 index 4f2aaea..0000000 --- a/Tests/CMakeTests/CheckSourceTreeTest.cmake.in +++ /dev/null @@ -1,365 +0,0 @@ -# Check the CMake source tree and report anything suspicious... -# -message("=============================================================================") -message("CTEST_FULL_OUTPUT (Avoid ctest truncation of output)") -message("") -message("CMake_BINARY_DIR='${CMake_BINARY_DIR}'") -message("CMake_SOURCE_DIR='${CMake_SOURCE_DIR}'") -message("GIT_EXECUTABLE='${GIT_EXECUTABLE}'") -message("HOME='${HOME}'") -message("ENV{DASHBOARD_TEST_FROM_CTEST}='$ENV{DASHBOARD_TEST_FROM_CTEST}'") -message("") -string(REPLACE "\\" "\\\\" HOME "${HOME}") - - -# Is the build directory the same as or underneath the source directory? -# (i.e. - is it an "in source" build?) -# -set(in_source_build 0) -set(build_under_source 0) - -string(FIND "${CMake_BINARY_DIR}" "${CMake_SOURCE_DIR}/" pos) -if(pos EQUAL 0) - message("build dir is *inside* source dir") - set(build_under_source 1) -elseif(CMake_SOURCE_DIR STREQUAL "${CMake_BINARY_DIR}") - message("build dir *is* source dir") - set(in_source_build 1) -else() - string(LENGTH "${CMake_SOURCE_DIR}" src_len) - string(LENGTH "${CMake_BINARY_DIR}" bin_len) - - if(bin_len GREATER src_len) - math(EXPR substr_len "${src_len}+1") - string(SUBSTRING "${CMake_BINARY_DIR}" 0 ${substr_len} bin_dir) - if(bin_dir STREQUAL "${CMake_SOURCE_DIR}/") - message("build dir is under source dir") - set(in_source_build 1) - endif() - endif() -endif() - -message("src_len='${src_len}'") -message("bin_len='${bin_len}'") -message("substr_len='${substr_len}'") -message("bin_dir='${bin_dir}'") -message("in_source_build='${in_source_build}'") -message("build_under_source='${build_under_source}'") -message("") - -if(build_under_source) - message(STATUS "Skipping rest of test because build tree is under source tree") - return() -endif() - -# If this does not appear to be a git checkout, just pass the test here -# and now. (Do not let the test fail if it is run in a tree *exported* from a -# repository or unpacked from a .zip file source installer...) -# -set(is_git_checkout 0) -if(EXISTS "${CMake_SOURCE_DIR}/.git") - set(is_git_checkout 1) -endif() - -message("is_git_checkout='${is_git_checkout}'") -message("") - -if(NOT is_git_checkout) - message("source tree is not a git checkout... test passes by early return...") - return() -endif() - -# This test looks for the following types of changes in the source tree: -# -set(additions 0) -set(conflicts 0) -set(modifications 0) -set(nonadditions 0) - -# ov == output variable... conditionally filled in by either git below: -# -set(cmd "") -set(ov "") -set(ev "") -set(rv "") - -# If no GIT_EXECUTABLE, see if we can figure out which git was used -# for the ctest_update step on this dashboard... -# -if(is_git_checkout AND NOT GIT_EXECUTABLE) - set(ctest_ini_file "") - set(exe "") - - # Use the old name: - if(EXISTS "${CMake_BINARY_DIR}/DartConfiguration.tcl") - set(ctest_ini_file "${CMake_BINARY_DIR}/DartConfiguration.tcl") - endif() - - # But if it exists, prefer the new name: - if(EXISTS "${CMake_BINARY_DIR}/CTestConfiguration.ini") - set(ctest_ini_file "${CMake_BINARY_DIR}/CTestConfiguration.ini") - endif() - - # If there is a ctest ini file, read the update command or git command - # from it: - # - if(ctest_ini_file) - file(STRINGS "${ctest_ini_file}" line REGEX "^GITCommand: (.*)$") - string(REGEX REPLACE "^GITCommand: (.*)$" "\\1" line "${line}") - if("${line}" MATCHES "^\"") - string(REGEX REPLACE "^\"([^\"]+)\" *.*$" "\\1" line "${line}") - else() - string(REGEX REPLACE "^([^ ]+) *.*$" "\\1" line "${line}") - endif() - set(exe "${line}") - if("${exe}" STREQUAL "GITCOMMAND-NOTFOUND") - set(exe "") - endif() - if(exe) - message("info: GIT_EXECUTABLE set by 'GITCommand:' from '${ctest_ini_file}'") - endif() - - if(NOT exe) - file(STRINGS "${ctest_ini_file}" line REGEX "^UpdateCommand: (.*)$") - string(REGEX REPLACE "^UpdateCommand: (.*)$" "\\1" line "${line}") - if("${line}" MATCHES "^\"") - string(REGEX REPLACE "^\"([^\"]+)\" *.*$" "\\1" line "${line}") - else() - string(REGEX REPLACE "^([^ ]+) *.*$" "\\1" line "${line}") - endif() - set(exe "${line}") - if("${exe}" STREQUAL "GITCOMMAND-NOTFOUND") - set(exe "") - endif() - if(exe) - message("info: GIT_EXECUTABLE set by 'UpdateCommand:' from '${ctest_ini_file}'") - endif() - endif() - else() - message("info: no DartConfiguration.tcl or CTestConfiguration.ini file...") - endif() - - # If we have still not grokked the exe, look in the Update.xml file to see - # if we can parse it from there... - # - if(NOT exe) - file(GLOB_RECURSE update_xml_file "${CMake_BINARY_DIR}/Testing/Update.xml") - if(update_xml_file) - file(STRINGS "${update_xml_file}" line - REGEX "^.*<UpdateCommand>(.*)</UpdateCommand>$" LIMIT_COUNT 1) - string(REPLACE ""\;" "\"" line "${line}") - string(REGEX REPLACE "^.*<UpdateCommand>(.*)</UpdateCommand>$" "\\1" line "${line}") - if("${line}" MATCHES "^\"") - string(REGEX REPLACE "^\"([^\"]+)\" *.*$" "\\1" line "${line}") - else() - string(REGEX REPLACE "^([^ ]+) *.*$" "\\1" line "${line}") - endif() - if(line) - set(exe "${line}") - endif() - if(exe) - message("info: GIT_EXECUTABLE set by '<UpdateCommand>' from '${update_xml_file}'") - endif() - else() - message("info: no Update.xml file...") - endif() - endif() - - if(exe) - set(GIT_EXECUTABLE "${exe}") - message("GIT_EXECUTABLE='${GIT_EXECUTABLE}'") - message("") - - if(NOT EXISTS "${GIT_EXECUTABLE}") - message(FATAL_ERROR "GIT_EXECUTABLE does not exist...") - endif() - else() - message(FATAL_ERROR "could not determine GIT_EXECUTABLE...") - endif() -endif() - - -if(is_git_checkout AND GIT_EXECUTABLE) - # Check with "git status" if there are any local modifications to the - # CMake source tree: - # - message("=============================================================================") - message("This is a git checkout, using git to verify source tree....") - message("") - - execute_process(COMMAND ${GIT_EXECUTABLE} --version - WORKING_DIRECTORY ${CMake_SOURCE_DIR} - OUTPUT_VARIABLE version_output - OUTPUT_STRIP_TRAILING_WHITESPACE) - message("=== output of 'git --version' ===") - message("${version_output}") - message("=== end output ===") - message("") - - execute_process(COMMAND ${GIT_EXECUTABLE} branch -a - WORKING_DIRECTORY ${CMake_SOURCE_DIR} - OUTPUT_VARIABLE git_branch_output - OUTPUT_STRIP_TRAILING_WHITESPACE) - message("=== output of 'git branch -a' ===") - message("${git_branch_output}") - message("=== end output ===") - message("") - - execute_process(COMMAND ${GIT_EXECUTABLE} log -1 - WORKING_DIRECTORY ${CMake_SOURCE_DIR} - OUTPUT_VARIABLE git_log_output - OUTPUT_STRIP_TRAILING_WHITESPACE) - message("=== output of 'git log -1' ===") - message("${git_log_output}") - message("=== end output ===") - message("") - - message("Copy/paste this command to reproduce:") - message("cd \"${CMake_SOURCE_DIR}\" && \"${GIT_EXECUTABLE}\" status") - message("") - - set(cmd ${GIT_EXECUTABLE} status) -endif() - - -if(cmd) - # Use the HOME value passed in to the script for calling git so it can - # find its user/global config settings... - # - set(original_ENV_HOME "$ENV{HOME}") - set(ENV{HOME} "${HOME}") - - execute_process(COMMAND ${cmd} - WORKING_DIRECTORY ${CMake_SOURCE_DIR} - OUTPUT_VARIABLE ov - ERROR_VARIABLE ev - RESULT_VARIABLE rv) - - set(ENV{HOME} "${original_ENV_HOME}") - - message("Results of running ${cmd}") - message("rv='${rv}'") - message("ov='${ov}'") - message("ev='${ev}'") - message("") - - if(NOT rv STREQUAL 0) - if(is_git_checkout AND (rv STREQUAL "1")) - # Many builds of git return "1" from a "nothing is changed" git status call... - # Do not fail with an error for rv==1 with git... - else() - message(FATAL_ERROR "error: ${cmd} attempt failed... (see output above)") - endif() - endif() -else() - message(FATAL_ERROR "error: no COMMAND to run to analyze source tree...") -endif() - - -# Analyze output: -# -if(NOT ov STREQUAL "") - string(REPLACE ";" "\\\\;" lines "${ov}") - string(REPLACE "\n" "E;" lines "${lines}") - - foreach(line ${lines}) - message("'${line}'") - - # But do not consider files that exist just because some user poked around - # the file system with Windows Explorer or with the Finder from a Mac... - # ('Thumbs.db' and '.DS_Store' files...) - # - set(consider 1) - set(ignore_files_regex "^(. |.*(/|\\\\))(\\.DS_Store|Thumbs.db)E$") - if(line MATCHES "${ignore_files_regex}") - message(" line matches '${ignore_files_regex}' -- not considered") - set(consider 0) - endif() - - if(consider) - if(is_git_checkout) - if(line MATCHES "^#?[ \t]*modified:") - message(" locally modified file detected...") - set(modifications 1) - endif() - - if(line MATCHES "^(# )?Untracked") - message(" locally non-added file/directory detected...") - set(nonadditions 1) - endif() - endif() - endif() - endforeach() -endif() - - -message("=============================================================================") -message("additions='${additions}'") -message("conflicts='${conflicts}'") -message("modifications='${modifications}'") -message("nonadditions='${nonadditions}'") -message("") - - -# Decide if the test passes or fails: -# -message("=============================================================================") - -if("$ENV{DASHBOARD_TEST_FROM_CTEST}" STREQUAL "") - - # developers are allowed to have local additions and modifications... - message("interactive test run") - message("") - -else() - - message("dashboard test run") - message("") - - # but dashboard machines are not allowed to have local additions or modifications... - if(additions) - message(FATAL_ERROR "test fails: local source tree additions") - endif() - - if(modifications) - message(FATAL_ERROR "test fails: local source tree modifications") - endif() - - # - # It's a dashboard run if ctest was run with '-D ExperimentalTest' or some - # other -D arg on its command line or if ctest is running a -S script to run - # a dashboard... Running ctest like that sets the DASHBOARD_TEST_FROM_CTEST - # env var. - # - -endif() - - -# ...and nobody is allowed to have local non-additions or conflicts... -# Not even developers. -# -if(nonadditions) - if(in_source_build) - message(" -warning: test results confounded because this is an 'in-source' build - cannot -distinguish between non-added files that are in-source build products and -non-added source files that somebody forgot to 'git add'... - this is only ok -if this is intentionally an in-source dashboard build... Developers should -use out-of-source builds to verify a clean source tree with this test... - -Allowing test to pass despite the warning message... -") - else() - message(FATAL_ERROR "test fails: local source tree non-additions: use git add before committing, or remove the files from the source tree") - endif() -endif() - -if(conflicts) - message(FATAL_ERROR "test fails: local source tree conflicts: resolve before committing") -endif() - - -# Still here? Good then... -# -message("test passes") -message("") diff --git a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in index 63c234a..7acfcd9 100644 --- a/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in +++ b/Tests/CMakeTests/ImplicitLinkInfoTest.cmake.in @@ -13,72 +13,84 @@ set(linux64_gcc_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-h set(linux64_gcc_libs "gcc;gcc_s;c;gcc;gcc_s") set(linux64_gcc_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu") list(APPEND platforms linux64_gcc) +list(APPEND langs C) # g++ dummy.cxx -v set(linux64_g++_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../.. -L/usr/lib/x86_64-linux-gnu /tmp/ccalRBlq.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crtn.o") set(linux64_g++_libs "stdc++;m;gcc_s;gcc;c;gcc_s;gcc") set(linux64_g++_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu") list(APPEND platforms linux64_g++) +list(APPEND langs CXX) # f95 dummy.f -v set(linux64_f95_text " /usr/lib/gcc/x86_64-linux-gnu/4.3.3/collect2 --eh-frame-hdr -m elf_x86_64 --hash-style=both -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3 -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../.. -L/usr/lib/x86_64-linux-gnu /tmp/ccAVcN7N.o -lgfortranbegin -lgfortran -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.3.3/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.3.3/../../../../lib/crtn.o") set(linux64_f95_libs "gfortranbegin;gfortran;m;gcc_s;gcc;c;gcc_s;gcc") set(linux64_f95_dirs "/usr/lib/gcc/x86_64-linux-gnu/4.3.3;/usr/lib;/lib;/usr/lib/x86_64-linux-gnu") list(APPEND platforms linux64_f95) +list(APPEND langs Fortran) # suncc dummy.c '-#' set(linux64_suncc_text "/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/sun/sunstudio12/prod/lib/amd64/crti.o /opt/sun/sunstudio12/prod/lib/amd64/crt1x.o /opt/sun/sunstudio12/prod/lib/amd64/values-xa.o dummy.o -Y \"/opt/sun/sunstudio12/prod/lib/amd64:/lib64:/usr/lib64\" -Qy -lc /opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a /opt/sun/sunstudio12/prod/lib/amd64/crtn.o") set(linux64_suncc_libs "c;/opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a") set(linux64_suncc_dirs "/opt/sun/sunstudio12/prod/lib/amd64;/lib64;/usr/lib64") list(APPEND platforms linux64_suncc) +list(APPEND langs C) # sunCC dummy.cxx -v set(linux64_sunCC_text "/opt/sun/sunstudio12/prod/lib/amd64/ld -u __1cH__CimplKcplus_init6F_v_ --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -R/opt/sun/sunstudio12/lib/rw7/amd64:/opt/sun/sunstudio12/lib/amd64:/opt/sun/sunstudio12/rtlibs/amd64:/opt/sun/lib/rtlibs/amd64:/opt/SUNWspro/lib/amd64:/lib64:/usr/lib64 -o a.out /opt/sun/sunstudio12/prod/lib/amd64/crti.o /opt/sun/sunstudio12/prod/lib/amd64/CCrti.o /opt/sun/sunstudio12/prod/lib/amd64/crt1x.o -Y P,/opt/sun/sunstudio12/lib/rw7/amd64:/opt/sun/sunstudio12/lib/amd64:/opt/sun/sunstudio12/rtlibs/amd64:/opt/sun/sunstudio12/prod/lib/rw7/amd64:/opt/sun/sunstudio12/prod/lib/amd64:/lib64:/usr/lib64 dummy.o -lCstd -lCrun -lm -lc /opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a /opt/sun/sunstudio12/prod/lib/amd64/CCrtn.o /opt/sun/sunstudio12/prod/lib/amd64/crtn.o >&/tmp/ld.04973.2.err") set(linux64_sunCC_libs "Cstd;Crun;m;c;/opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a") set(linux64_sunCC_dirs "/opt/sun/sunstudio12/lib/rw7/amd64;/opt/sun/sunstudio12/lib/amd64;/opt/sun/sunstudio12/rtlibs/amd64;/opt/sun/sunstudio12/prod/lib/rw7/amd64;/opt/sun/sunstudio12/prod/lib/amd64;/lib64;/usr/lib64") list(APPEND platforms linux64_sunCC) +list(APPEND langs CXX) # sunf90 dummy.f -v set(linux64_sunf90_text "/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -R/opt/sun/sunstudio12/lib/amd64:/opt/sun/sunstudio12/rtlibs/amd64:/opt/sun/lib/rtlibs/amd64 -o a.out /opt/sun/sunstudio12/prod/lib/amd64/crti.o /opt/sun/sunstudio12/prod/lib/amd64/crt1x.o /opt/sun/sunstudio12/prod/lib/amd64/values-xi.o -Y P,/opt/sun/sunstudio12/lib/amd64:/opt/sun/sunstudio12/rtlibs/amd64:/opt/sun/sunstudio12/prod/lib/amd64:/lib64:/usr/lib64 dummy.o -lfui -lfai -lfsu -Bdynamic -lmtsk -lpthread -lm -lc /opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a /opt/sun/sunstudio12/prod/lib/amd64/crtn.o") set(linux64_sunf90_libs "fui;fai;fsu;mtsk;pthread;m;c;/opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a") set(linux64_sunf90_dirs "/opt/sun/sunstudio12/lib/amd64;/opt/sun/sunstudio12/rtlibs/amd64;/opt/sun/sunstudio12/prod/lib/amd64;/lib64;/usr/lib64") list(APPEND platforms linux64_sunf90) +list(APPEND langs Fortran) # icc dummy.c -v set(linux64_icc_text "ld /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /tmp/iccBP8OfN.o -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib -Bstatic -limf -lsvml -Bdynamic -lm -Bstatic -lipgo -ldecimal -lirc -Bdynamic -lgcc_s -lgcc -Bstatic -lirc -Bdynamic -lc -lgcc_s -lgcc -Bstatic -lirc_s -Bdynamic -ldl -lc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o") set(linux64_icc_libs "imf;svml;m;ipgo;decimal;irc;gcc_s;gcc;irc;c;gcc_s;gcc;irc_s;dl;c") set(linux64_icc_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib") list(APPEND platforms linux64_icc) +list(APPEND langs C) # icxx dummy.cxx -v set(linux64_icxx_text "ld /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /tmp/icpc270GoT.o -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib -Bstatic -limf -lsvml -Bdynamic -lm -Bstatic -lipgo -ldecimal -Bdynamic -lstdc++ -Bstatic -lirc -Bdynamic -lgcc_s -lgcc -Bstatic -lirc -Bdynamic -lc -lgcc_s -lgcc -Bstatic -lirc_s -Bdynamic -ldl -lc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o") set(linux64_icxx_libs "imf;svml;m;ipgo;decimal;stdc++;irc;gcc_s;gcc;irc;c;gcc_s;gcc;irc_s;dl;c") set(linux64_icxx_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib") list(APPEND platforms linux64_icxx) +list(APPEND langs CXX) # ifort dummy.f -v set(linux64_ifort_text "ld --eh-frame-hdr -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out -L/opt/compiler/intel/compiler/11.0/lib/intel64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../x86_64-suse-linux/lib -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../.. -L/lib64 -L/lib -L/usr/lib64 -L/usr/lib /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crt1.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crti.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o /opt/compiler/intel/compiler/11.0/lib/intel64/for_main.o dum.cxx -Bstatic -lifport -lifcore -limf -lsvml -Bdynamic -lm -Bstatic -lipgo -lirc -Bdynamic -lpthread -lc -lgcc_s -lgcc -Bstatic -lirc_s -Bdynamic -ldl -lc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/../../../../lib64/crtn.o") set(linux64_ifort_libs "ifport;ifcore;imf;svml;m;ipgo;irc;pthread;c;gcc_s;gcc;irc_s;dl;c") set(linux64_ifort_dirs "/opt/compiler/intel/compiler/11.0/lib/intel64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2;/usr/lib64;/lib64;/usr/x86_64-suse-linux/lib;/lib;/usr/lib") list(APPEND platforms linux64_ifort) +list(APPEND langs Fortran) # pgcc dummy.c -v set(linux64_pgcc_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgcc7OscXa5ur7Zk.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lnspgc -lpgc -lm -lgcc -lc -lgcc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/crtn.o") set(linux64_pgcc_libs "nspgc;pgc;m;gcc;c;gcc") set(linux64_pgcc_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2") list(APPEND platforms linux64_pgcc) +list(APPEND langs C) # pgCC dummy.cxx -v set(linux64_pgCC_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgCCFhjcDt1fs1Ki.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lstd -lC -lnspgc -lpgc -lm -lgcc -lc -lgcc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/crtn.o") set(linux64_pgCC_libs "std;C;nspgc;pgc;m;gcc;c;gcc") set(linux64_pgCC_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2") list(APPEND platforms linux64_pgCC) +list(APPEND langs CXX) # pgf90 dummy.f -v set(linux64_pgf90_text "/usr/bin/ld /usr/lib64/crt1.o /usr/lib64/crti.o /opt/compiler/pgi/linux86-64/8.0-3/lib/trace_init.o /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtbegin.o /opt/compiler/pgi/linux86-64/8.0-3/lib/f90main.o -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/compiler/pgi/linux86-64/8.0-3/lib/pgi.ld -L/opt/compiler/pgi/linux86-64/8.0-3/lib -L/usr/lib64 -L/usr/lib64/gcc/x86_64-suse-linux/4.1.2 /tmp/pgf90QOIc_eB9xY5h.o -rpath /opt/compiler/pgi/linux86-64/8.0-3/lib -lpgf90 -lpgf90_rpm1 -lpgf902 -lpgf90rtl -lpgftnrtl -lnspgc -lpgc -lrt -lpthread -lm -lgcc -lc -lgcc /usr/lib64/gcc/x86_64-suse-linux/4.1.2/crtend.o /usr/lib64/crtn.o") set(linux64_pgf90_libs "pgf90;pgf90_rpm1;pgf902;pgf90rtl;pgftnrtl;nspgc;pgc;rt;pthread;m;gcc;c;gcc") set(linux64_pgf90_dirs "/opt/compiler/pgi/linux86-64/8.0-3/lib;/usr/lib64;/usr/lib64/gcc/x86_64-suse-linux/4.1.2") list(APPEND platforms linux64_pgf90) +list(APPEND langs Fortran) # nagfor dummy.f -Wl,-v set(linux64_nagfor_text " /usr/libexec/gcc/x86_64-redhat-linux/4.4.5/collect2 --no-add-needed --eh-frame-hdr --build-id -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../.. /usr/local/NAG/lib/f90_init.o /usr/local/NAG/lib/quickfit.o dummy.o -rpath /usr/local/NAG/lib /usr/local/NAG/lib/libf53.so /usr/local/NAG/lib/libf53.a -lm -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.4.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crtn.o") @@ -86,6 +98,7 @@ set(linux64_nagfor_libs "/usr/local/NAG/lib/f90_init.o;/usr/local/NAG/lib/quickf set(linux64_nagfor_dirs "/usr/lib/gcc/x86_64-redhat-linux/4.4.5;/usr/lib64;/lib64;/usr/lib") set(linux64_nagfor_obj_regex "^/usr/local/NAG/lib") list(APPEND platforms linux64_nagfor) +list(APPEND langs Fortran) # absoft dummy.f -X -v set(linux64_absoft_text "collect2 version 4.4.5 (x86-64 Linux/ELF) @@ -93,6 +106,7 @@ set(linux64_absoft_text "collect2 version 4.4.5 (x86-64 Linux/ELF) set(linux64_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;pthread;gcc;gcc_s;c;gcc;gcc_s") set(linux64_absoft_dirs "/opt/absoft11.1/lib64;/usr/lib/gcc/x86_64-linux-gnu/4.4.5;/usr/lib;/lib") list(APPEND platforms linux64_absoft) +list(APPEND langs Fortran) # gcc dummy.c -v # in strange path set(linux64_test1_text " @@ -101,12 +115,14 @@ ${linux64_gcc_text}") set(linux64_test1_libs "${linux64_gcc_libs}") set(linux64_test1_dirs "${linux64_gcc_dirs}") list(APPEND platforms linux64_test1) +list(APPEND langs C) # sunCC dummy.cxx -v # extra slashes set(linux64_test2_text "/usr/bin/ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /opt/sun/sunstudio12/prod/lib/amd64//crti.o /opt/sun/sunstudio12/prod/lib/amd64/crt1x.o /opt/sun/sunstudio12/prod/lib/amd64/values-xa.o dummy.o -Y \"/opt/sun/sunstudio12/prod/lib//amd64:/lib64:/usr//lib64\" -Qy -lc /opt/sun/sunstudio12/prod/lib/amd64//libc_supp.a /opt/sun/sunstudio12/prod/lib/amd64/crtn.o") set(linux64_test2_libs "c;/opt/sun/sunstudio12/prod/lib/amd64/libc_supp.a") set(linux64_test2_dirs "/opt/sun/sunstudio12/prod/lib/amd64;/lib64;/usr/lib64") list(APPEND platforms linux64_test2) +list(APPEND langs CXX) # -specs=redhat-hardened-ld set(linux64_test3_text "COLLECT_GCC_OPTIONS='-specs=/usr/lib/rpm/redhat/redhat-hardened-ld' '-v' '-O2' '-g' '-pipe' '-Wall' '-Werror=format-security' '-fexceptions' '-fstack-protector-strong' '--param' 'ssp-buffer-size=4' '-grecord-gcc-switches' '-specs=/usr/lib/rpm/redhat/redhat-hardened-cc1' '-m64' '-mtune=generic' '-I' '/usr/lib64/gfortran/modules' '-o' 'a.out' '-rdynamic' '-shared-libgcc' '-march=x86-64' '-pie' @@ -114,12 +130,14 @@ set(linux64_test3_text "COLLECT_GCC_OPTIONS='-specs=/usr/lib/rpm/redhat/redhat-h set(linux64_test3_libs "gfortran;m;gcc_s;gcc;quadmath;m;gcc_s;gcc;c;gcc_s;gcc") set(linux64_test3_dirs "/usr/lib/gcc/x86_64-redhat-linux/5.1.1;/usr/lib64;/lib64;/usr/lib") list(APPEND platforms linux64_test3) +list(APPEND langs Fortran) # clang -fsanitize=memory set(linux64_clang_sanitize_memory_text [[ "/usr/bin/ld" --hash-style=both --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o a.out /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../.. -L/usr/lib/llvm-3.8/bin/../lib -L/lib -L/usr/lib -whole-archive /usr/lib/llvm-3.8/bin/../lib/clang/3.8.0/lib/linux/libclang_rt.msan-x86_64.a -no-whole-archive --dynamic-list=/usr/lib/llvm-3.8/bin/../lib/clang/3.8.0/lib/linux/libclang_rt.msan-x86_64.a.syms /tmp/dummy-27898d.o --no-as-needed -lpthread -lrt -lm -ldl -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/crtn.o]]) set(linux64_clang_sanitize_memory_libs "pthread;rt;m;dl;gcc;gcc_s;c;gcc;gcc_s") set(linux64_clang_sanitize_memory_dirs "/usr/lib/gcc/x86_64-linux-gnu/5.4.0;/usr/lib/x86_64-linux-gnu;/lib/x86_64-linux-gnu;/lib64;/usr/lib;/usr/lib/llvm-3.8/lib;/lib") list(APPEND platforms linux64_clang_sanitize_memory) +list(APPEND langs C) #----------------------------------------------------------------------------- # Mac @@ -144,12 +162,14 @@ set(mac_i686_gcc_Wlv_libs "gcc") set(mac_i686_gcc_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") set(mac_i686_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_gcc_Wlv) +list(APPEND langs C) # gcc -arch i686 dummy.c -v set(mac_i686_gcc_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccnhXAGL.o -lSystem -lgcc -lSystem") set(mac_i686_gcc_libs "gcc") set(mac_i686_gcc_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_i686_gcc) +list(APPEND langs C) # g++ -arch i686 dummy.cxx -v -Wl,-v set(mac_i686_g++_Wlv_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem @@ -171,12 +191,14 @@ set(mac_i686_g++_Wlv_libs "stdc++;gcc") set(mac_i686_g++_Wlv_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") set(mac_i686_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_g++_Wlv) +list(APPEND langs CXX) # g++ -arch i686 dummy.cxx -v set(mac_i686_g++_text " /usr/libexec/gcc/i686-apple-darwin10/4.2.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.6.o -L/usr/lib/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../../i686-apple-darwin10/4.2.1 -L/usr/lib/gcc/i686-apple-darwin10/4.2.1/../../.. /var/tmp//ccEXXICh.o -lstdc++ -lSystem -lgcc -lSystem") set(mac_i686_g++_libs "stdc++;gcc") set(mac_i686_g++_dirs "/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_i686_g++) +list(APPEND langs CXX) # gfortran dummy.f -v -Wl,-v set(mac_i686_gfortran_Wlv_text " /usr/local/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//cc9zXNax.o -v -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem @@ -195,12 +217,14 @@ set(mac_i686_gfortran_Wlv_libs "gfortranbegin;gfortran;gcc_s.10.5;gcc") set(mac_i686_gfortran_Wlv_dirs "/usr/local/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/local/lib;/usr/lib") set(mac_i686_gfortran_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_i686_gfortran_Wlv) +list(APPEND langs Fortran) # gfortran dummy.f -v set(mac_i686_gfortran_text " /usr/libexec/gcc/i386-apple-darwin9.7.0/4.4.1/collect2 -dynamic -arch i386 -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1 -L/usr/lib/gcc -L/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1/../../.. /var/tmp//ccgqbX5P.o -lgfortranbegin -lgfortran -lgcc_s.10.5 -lgcc -lSystem") set(mac_i686_gfortran_libs "gfortranbegin;gfortran;gcc_s.10.5;gcc") set(mac_i686_gfortran_dirs "/usr/lib/gcc/i386-apple-darwin9.7.0/4.4.1;/usr/lib/gcc;/usr/lib") list(APPEND platforms mac_i686_gfortran) +list(APPEND langs Fortran) # gcc -arch ppc dummy.c -v -Wl,-v set(mac_ppc_gcc_Wlv_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//cclziQY4.o -v -lgcc -lSystemStubs -lSystem @@ -222,12 +246,14 @@ set(mac_ppc_gcc_Wlv_libs "gcc") set(mac_ppc_gcc_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") set(mac_ppc_gcc_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_ppc_gcc_Wlv) +list(APPEND langs C) # gcc -arch ppc dummy.c -v set(mac_ppc_gcc_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccdcolsP.o -lgcc -lSystemStubs -lSystem") set(mac_ppc_gcc_libs "gcc") set(mac_ppc_gcc_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_ppc_gcc) +list(APPEND langs C) # g++ -arch ppc dummy.cxx -v -Wl,-v set(mac_ppc_g++_Wlv_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccaFTkwq.o -v -lstdc++ -lgcc -lSystemStubs -lSystem @@ -249,12 +275,14 @@ set(mac_ppc_g++_Wlv_libs "stdc++;gcc") set(mac_ppc_g++_Wlv_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib;/usr/local/lib") set(mac_ppc_g++_Wlv_fwks "/Library/Frameworks;/System/Library/Frameworks") list(APPEND platforms mac_ppc_g++_Wlv) +list(APPEND langs CXX) # g++ -arch ppc dummy.cxx -v set(mac_ppc_g++_text " /usr/libexec/gcc/powerpc-apple-darwin10/4.2.1/collect2 -dynamic -arch ppc -macosx_version_min 10.6.0 -weak_reference_mismatches non-weak -o a.out -lcrt1.10.5.o -L/usr/lib/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../../powerpc-apple-darwin10/4.2.1 -L/usr/lib/gcc/powerpc-apple-darwin10/4.2.1/../../.. /var/tmp//ccbjB6Lj.o -lstdc++ -lgcc -lSystemStubs -lSystem") set(mac_ppc_g++_libs "stdc++;gcc") set(mac_ppc_g++_dirs "/usr/lib/powerpc-apple-darwin10/4.2.1;/usr/lib/gcc/powerpc-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_ppc_g++) +list(APPEND langs CXX) # absoft dummy.f -X -v set(mac_absoft_text "collect2 version 4.2.1 (Apple Inc. build 5664) (i686 Darwin) @@ -263,12 +291,14 @@ set(mac_absoft_text "collect2 version 4.2.1 (Apple Inc. build 5664) (i686 Darwin set(mac_absoft_libs "af90math;afio;amisc;absoftmain;af77math;m;mv;gcc") set(mac_absoft_dirs "/Applications/Absoft11.1/lib;/usr/lib/i686-apple-darwin10/4.2.1;/usr/lib/gcc/i686-apple-darwin10/4.2.1;/usr/lib") list(APPEND platforms mac_absoft) +list(APPEND langs Fortran) # Xcode 8.3: clang++ dummy.cpp -v set(mac_clang_v_text " \"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld\" -demangle -lto_library /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libLTO.dylib -no_deduplicate -dynamic -arch x86_64 -macosx_version_min 10.12.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -o a.out /var/folders/hc/95l7dhnx459c57g4yg_6yd8c0000gp/T/dummy-384ea1.o -lc++ -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.1.0/lib/darwin/libclang_rt.osx.a") set(mac_clang_v_libs "c++") set(mac_clang_v_dirs "") list(APPEND platforms mac_clang_v) +list(APPEND langs CXX) #----------------------------------------------------------------------------- # Sun @@ -278,24 +308,28 @@ set(sun_cc_text "/usr/ccs/bin/ld /opt/SUNWspro/prod/lib/crti.o /opt/SUNWspro/pro set(sun_cc_libs "c") set(sun_cc_dirs "/opt/SUNWspro/prod/lib/v8plus;/opt/SUNWspro/prod/lib;/usr/ccs/lib;/lib;/usr/lib") list(APPEND platforms sun_cc) +list(APPEND langs C) # CC dummy.cxx -v set(sun_CC_text "/usr/ccs/bin/ld -u __1cH__CimplKcplus_init6F_v_ -zld32=-S/opt/SUNWspro/prod/lib/libldstab_ws.so -zld64=-S/opt/SUNWspro/prod/lib/v9/libldstab_ws.so -zld32=-S/opt/SUNWspro/prod/lib/libCCexcept.so.1 -zld64=-S/opt/SUNWspro/prod/lib/v9/libCCexcept.so.1 -R/opt/SUNWspro/lib/rw7:/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/lib:/usr/ccs/lib:/lib:/usr/lib -o a.out /opt/SUNWspro/prod/lib/crti.o /opt/SUNWspro/prod/lib/CCrti.o /opt/SUNWspro/prod/lib/crt1.o /opt/SUNWspro/prod/lib/misalign.o /opt/SUNWspro/prod/lib/values-xa.o -Y P,/opt/SUNWspro/lib/rw7:/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/prod/lib/rw7:/opt/SUNWspro/prod/lib/v8plus:/opt/SUNWspro/lib:/opt/SUNWspro/prod/lib:/usr/ccs/lib:/lib:/usr/lib dummy.o -lCstd -lCrun -lm -lc /opt/SUNWspro/prod/lib/CCrtn.o /opt/SUNWspro/prod/lib/crtn.o >&/tmp/ld.14846.2.err") set(sun_CC_libs "Cstd;Crun;m;c") set(sun_CC_dirs "/opt/SUNWspro/lib/rw7;/opt/SUNWspro/lib/v8plus;/opt/SUNWspro/prod/lib/rw7;/opt/SUNWspro/prod/lib/v8plus;/opt/SUNWspro/lib;/opt/SUNWspro/prod/lib;/usr/ccs/lib;/lib;/usr/lib") list(APPEND platforms sun_CC) +list(APPEND langs CXX) # f77 dummy.f -v set(sun_f77_text "/usr/ccs/bin/ld -t -R/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/lib -o a.out /opt/SUNWspro/prod/lib/crti.o /opt/SUNWspro/prod/lib/crt1.o /opt/SUNWspro/prod/lib/misalign.o /opt/SUNWspro/prod/lib/values-xi.o -Y P,/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/prod/lib/v8plus:/opt/SUNWspro/lib:/opt/SUNWspro/prod/lib:/usr/ccs/lib:/lib:/usr/lib dummy.o -lf77compat -zallextract -lompstubs -zdefaultextract -lfui -lfai -lfai2 -lfsumai -lfprodai -lfminlai -lfmaxlai -lfminvai -lfmaxvai -lfsu -lsunmath -lm -lc /opt/SUNWspro/prod/lib/crtn.o") set(sun_f77_libs "f77compat;-zallextract;ompstubs;-zdefaultextract;fui;fai;fai2;fsumai;fprodai;fminlai;fmaxlai;fminvai;fmaxvai;fsu;sunmath;m;c") set(sun_f77_dirs "/opt/SUNWspro/lib/v8plus;/opt/SUNWspro/prod/lib/v8plus;/opt/SUNWspro/lib;/opt/SUNWspro/prod/lib;/usr/ccs/lib;/lib;/usr/lib") list(APPEND platforms sun_f77) +list(APPEND langs Fortran) # f90 dummy.f -v set(sun_f90_text "/usr/ccs/bin/ld -t -R/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/lib -o a.out /opt/SUNWspro/prod/lib/crti.o /opt/SUNWspro/prod/lib/crt1.o /opt/SUNWspro/prod/lib/misalign.o /opt/SUNWspro/prod/lib/values-xi.o -Y P,/opt/SUNWspro/lib/v8plus:/opt/SUNWspro/prod/lib/v8plus:/opt/SUNWspro/lib:/opt/SUNWspro/prod/lib:/usr/ccs/lib:/lib:/usr/lib dummy.o -zallextract -lompstubs -zdefaultextract -lfui -lfai -lfai2 -lfsumai -lfprodai -lfminlai -lfmaxlai -lfminvai -lfmaxvai -lfsu -lsunmath -lm -lc /opt/SUNWspro/prod/lib/crtn.o") set(sun_f90_libs "-zallextract;ompstubs;-zdefaultextract;fui;fai;fai2;fsumai;fprodai;fminlai;fmaxlai;fminvai;fmaxvai;fsu;sunmath;m;c") set(sun_f90_dirs "/opt/SUNWspro/lib/v8plus;/opt/SUNWspro/prod/lib/v8plus;/opt/SUNWspro/lib;/opt/SUNWspro/prod/lib;/usr/ccs/lib;/lib;/usr/lib") list(APPEND platforms sun_f90) +list(APPEND langs Fortran) #----------------------------------------------------------------------------- # AIX @@ -305,12 +339,14 @@ set(aix_xlc_32_text "/bin/ld -b32 /lib/crt0.o -bpT:0x10000000 -bpD:0x20000000 du set(aix_xlc_32_libs "xlopt;xl;c") set(aix_xlc_32_dirs "/usr/vac/lib") list(APPEND platforms aix_xlc_32) +list(APPEND langs C) # xlc -q64 dummy.c -V set(aix_xlc_64_text "/bin/ld -b64 /lib/crt0_64.o -bpT:0x100000000 -bpD:0x110000000 dummy.o -L/usr/vac/lib -lxlopt -lxl -lc") set(aix_xlc_64_libs "xlopt;xl;c") set(aix_xlc_64_dirs "/usr/vac/lib") list(APPEND platforms aix_xlc_64) +list(APPEND langs C) # xlC -q32 dummy.cxx -V set(aix_xlC_32_text " @@ -319,6 +355,7 @@ set(aix_xlC_32_text " set(aix_xlC_32_libs "xlopt;xl;C;m;c") set(aix_xlC_32_dirs "/usr/vac/lib;/usr/vacpp/lib") list(APPEND platforms aix_xlC_32) +list(APPEND langs CXX) # xlC -q64 dummy.cxx -V set(aix_xlC_64_text " @@ -327,36 +364,42 @@ set(aix_xlC_64_text " set(aix_xlC_64_libs "xlopt;xl;C;m;c") set(aix_xlC_64_dirs "/usr/vac/lib;/usr/vacpp/lib") list(APPEND platforms aix_xlC_64) +list(APPEND langs CXX) # xlf -q32 dummy.f -V set(aix_xlf_32_text "/bin/ld -b32 /lib/crt0.o -bpT:0x10000000 -bpD:0x20000000 -bh:4 -bh:4 -bh:4 -bh:4 dummy.o -lxlf90 -L/usr/lpp/xlf/lib -lxlopt -lxlf -lxlomp_ser -lm -lc") set(aix_xlf_32_libs "xlf90;xlopt;xlf;xlomp_ser;m;c") set(aix_xlf_32_dirs "/usr/lpp/xlf/lib") list(APPEND platforms aix_xlf_32) +list(APPEND langs Fortran) # xlf -q64 dummy.f -V set(aix_xlf_64_text "/bin/ld -b64 /lib/crt0_64.o -bpT:0x100000000 -bpD:0x110000000 -bh:4 -bh:4 -bh:4 -bh:4 dummy.o -lxlf90 -L/usr/lpp/xlf/lib -lxlopt -lxlf -lxlomp_ser -lm -lc") set(aix_xlf_64_libs "xlf90;xlopt;xlf;xlomp_ser;m;c") set(aix_xlf_64_dirs "/usr/lpp/xlf/lib") list(APPEND platforms aix_xlf_64) +list(APPEND langs Fortran) # xlf90 -q32 dummy.f -V set(aix_xlf90_32_text "/bin/ld -b32 /lib/crt0.o -bpT:0x10000000 -bpD:0x20000000 -bh:4 dummy.o -lxlf90 -L/usr/lpp/xlf/lib -lxlopt -lxlf -lxlomp_ser -lm -lc") set(aix_xlf90_32_libs "xlf90;xlopt;xlf;xlomp_ser;m;c") set(aix_xlf90_32_dirs "/usr/lpp/xlf/lib") list(APPEND platforms aix_xlf90_32) +list(APPEND langs Fortran) # xlf90 -q64 dummy.f -V set(aix_xlf90_64_text "/bin/ld -b64 /lib/crt0_64.o -bpT:0x100000000 -bpD:0x110000000 -bh:4 dummy.o -lxlf90 -L/usr/lpp/xlf/lib -lxlopt -lxlf -lxlomp_ser -lm -lc") set(aix_xlf90_64_libs "xlf90;xlopt;xlf;xlomp_ser;m;c") set(aix_xlf90_64_dirs "/usr/lpp/xlf/lib") list(APPEND platforms aix_xlf90_64) +list(APPEND langs Fortran) # g++ dummy.c -v set(aix_g++_text " /prefix/libexec/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/collect2 -bpT:0x10000000 -bpD:0x20000000 -btextro /lib/crt0.o /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/crtcxa.o /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/crtdbase.o -L/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0 -L/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/../../.. /tmp//ccKROJ1f.o -lstdc++ -lm -lgcc_s /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a -lc -lgcc_s /prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a") set(aix_g++_libs "stdc++;m;gcc_s;/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a;c;gcc_s;/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0/libgcc.a") set(aix_g++_dirs "/prefix/lib/gcc/powerpc-ibm-aix7.2.0.0/7.2.0;/prefix/lib") list(APPEND platforms aix_g++) +list(APPEND langs CXX) #----------------------------------------------------------------------------- # HP @@ -367,6 +410,7 @@ set(hp_cc_old_text "cc: LPATH is /usr/lib/pa1.1:/usr/lib:/opt/langtools/lib: set(hp_cc_old_libs "c") set(hp_cc_old_dirs "/usr/lib/pa1.1;/usr/lib;/opt/langtools/lib") list(APPEND platforms hp_cc_old) +list(APPEND langs C) # aCC dummy.cxx -v set(hp_aCC_old_text "LPATH=/usr/lib/pa1.1:/usr/lib:/opt/langtools/lib @@ -374,6 +418,7 @@ set(hp_aCC_old_text "LPATH=/usr/lib/pa1.1:/usr/lib:/opt/langtools/lib set(hp_aCC_old_libs "std;stream;Csup;m;cl;c") set(hp_aCC_old_dirs "/usr/lib/pa1.1;/usr/lib;/opt/langtools/lib;/opt/aCC/lib") list(APPEND platforms hp_aCC_old) +list(APPEND langs CXX) # cc dummy.c -v set(hp_cc_32_text "LPATH=/usr/lib/hpux32:/opt/langtools/lib/hpux32 @@ -381,6 +426,7 @@ set(hp_cc_32_text "LPATH=/usr/lib/hpux32:/opt/langtools/lib/hpux32 set(hp_cc_32_libs "c") set(hp_cc_32_dirs "/usr/lib/hpux32;/opt/langtools/lib/hpux32") list(APPEND platforms hp_cc_32) +list(APPEND langs C) # cc +DD64 dummy.c -v set(hp_cc_64_text "LPATH=/usr/lib/hpux64:/opt/langtools/lib/hpux64 @@ -388,6 +434,7 @@ set(hp_cc_64_text "LPATH=/usr/lib/hpux64:/opt/langtools/lib/hpux64 set(hp_cc_64_libs "c") set(hp_cc_64_dirs "/usr/lib/hpux64;/opt/langtools/lib/hpux64") list(APPEND platforms hp_cc_64) +list(APPEND langs C) # aCC dummy.cxx -v set(hp_aCC_32_text "LPATH=/usr/lib/hpux32:/opt/langtools/lib/hpux32 @@ -395,6 +442,7 @@ set(hp_aCC_32_text "LPATH=/usr/lib/hpux32:/opt/langtools/lib/hpux32 set(hp_aCC_32_libs "std_v2;Csup;m;unwind;Csup;c;dl") set(hp_aCC_32_dirs "/usr/lib/hpux32;/opt/langtools/lib/hpux32;/opt/aCC/lib/hpux32") list(APPEND platforms hp_aCC_32) +list(APPEND langs CXX) # aCC +DD64 dummy.cxx -v set(hp_aCC_64_text "LPATH=/usr/lib/hpux64:/opt/langtools/lib/hpux64 @@ -402,6 +450,7 @@ set(hp_aCC_64_text "LPATH=/usr/lib/hpux64:/opt/langtools/lib/hpux64 set(hp_aCC_64_libs "std_v2;Csup;m;unwind;Csup;c;dl") set(hp_aCC_64_dirs "/usr/lib/hpux64;/opt/langtools/lib/hpux64;/opt/aCC/lib/hpux64") list(APPEND platforms hp_aCC_64) +list(APPEND langs CXX) # f90 dummy.f -v set(hp_f90_32_text "LPATH is: /usr/lib/hpux32/:/opt/langtools/lib/hpux32/ @@ -409,6 +458,7 @@ set(hp_f90_32_text "LPATH is: /usr/lib/hpux32/:/opt/langtools/lib/hpux32/ set(hp_f90_32_libs "-l:libF90.a;-l:libIO77.a;m;c;unwind;uca") set(hp_f90_32_dirs "/usr/lib/hpux32;/opt/langtools/lib/hpux32") list(APPEND platforms hp_f90_32) +list(APPEND langs Fortran) # f90 +DD64 dummy.f -v set(hp_f90_64_text "LPATH is: /usr/lib/hpux64/:/opt/langtools/lib/hpux64/ @@ -416,6 +466,7 @@ set(hp_f90_64_text "LPATH is: /usr/lib/hpux64/:/opt/langtools/lib/hpux64/ set(hp_f90_64_libs "-l:libF90.a;-l:libIO77.a;m;c;unwind;uca") set(hp_f90_64_dirs "/usr/lib/hpux64;/opt/langtools/lib/hpux64") list(APPEND platforms hp_f90_64) +list(APPEND langs Fortran) #----------------------------------------------------------------------------- # Cygwin @@ -425,12 +476,14 @@ set(cygwin_gcc_text " /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic - set(cygwin_gcc_libs "gcc;cygwin;user32;kernel32;advapi32;shell32;gcc") set(cygwin_gcc_dirs "/usr/lib/gcc/i686-pc-cygwin/3.4.4;/usr/lib") list(APPEND platforms cygwin_gcc) +list(APPEND langs C) # g++ dummy.cxx -v set(cygwin_g++_text " /usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic --dll-search-prefix=cyg /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../.. /home/user/AppData/Local/Temp/ccsvcDO6.o -lstdc++ -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc") set(cygwin_g++_libs "stdc++;gcc;cygwin;user32;kernel32;advapi32;shell32;gcc") set(cygwin_g++_dirs "/usr/lib/gcc/i686-pc-cygwin/3.4.4;/usr/lib") list(APPEND platforms cygwin_g++) +list(APPEND langs CXX) # gfortran dummy.f -v set(cygwin_gfortran_text "Configured with: ... LD=/opt/gcc-tools/bin/ld.exe @@ -439,6 +492,7 @@ set(cygwin_gfortran_text "Configured with: ... LD=/opt/gcc-tools/bin/ld.exe set(cygwin_gfortran_libs "gfortranbegin;gfortran;gcc_s;gcc_s;gcc;cygwin;user32;kernel32;advapi32;shell32;gcc_s;gcc_s;gcc") set(cygwin_gfortran_dirs "/usr/lib/gcc/i686-pc-cygwin/4.3.2;/usr/lib") list(APPEND platforms cygwin_gfortran) +list(APPEND langs Fortran) #----------------------------------------------------------------------------- # MSYS @@ -448,18 +502,21 @@ set(msys_gcc_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe set(msys_gcc_libs "mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex") set(msys_gcc_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib") list(APPEND platforms msys_gcc) +list(APPEND langs C) # g++ dummy.cxx -v set(msys_g++_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/cci5hYPk.o -lstdc++ -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtend.o") set(msys_g++_libs "stdc++;mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex") set(msys_g++_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib") list(APPEND platforms msys_g++) +list(APPEND langs CXX) # g77 dummy.f -v set(msys_g77_text " C:/some-mingw/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe -Bdynamic /some-mingw/lib/crt2.o C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5 -LC:/some-mingw/bin/../lib/gcc -L/some-mingw/lib -LC:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/../../.. C:/home/user/AppData/Local/Temp/ccabRxQ1.o -lfrtbegin -lg2c -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt C:/some-mingw/bin/../lib/gcc/mingw32/3.4.5/crtend.o") set(msys_g77_libs "frtbegin;g2c;mingw32;gcc;moldname;mingwex;user32;kernel32;advapi32;shell32;mingw32;gcc;moldname;mingwex") set(msys_g77_dirs "C:/some-mingw/lib/gcc/mingw32/3.4.5;C:/some-mingw/lib/gcc;/some-mingw/lib;C:/some-mingw/lib") list(APPEND platforms msys_g77) +list(APPEND langs Fortran) #----------------------------------------------------------------------------- # MSYS2-runtime @@ -469,18 +526,21 @@ set(msys2rt_gcc_text " /usr/lib/gcc/i686-pc-msys/6.4.0/collect2.exe -Bdynamic -- set(msys2rt_gcc_libs "msys-2.0;user32;kernel32;advapi32;shell32") set(msys2rt_gcc_dirs "/usr/lib/gcc/i686-pc-msys/6.4.0;/usr/lib") list(APPEND platforms msysrt_gcc) +list(APPEND langs C) # g++ dummy.cxx -v set(msys2rt_g++_text " /usr/lib/gcc/i686-pc-msys/6.4.0/collect2.exe -Bdynamic --dll-search-prefix=msys- /usr/lib/gcc/i686-pc-msys/6.4.0/../../../crt0.o -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0/../../.. /home/user/AppData/Local/Temp/ccsvcDO6.o -lstdc++ -lgcc -lmsys-2.0 -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc") set(msys2rt_g++_libs "stdc++;msys-2.0;user32;kernel32;advapi32;shell32") set(msys2rt_g++_dirs "/usr/lib/gcc/i686-pc-msys/6.4.0;/usr/lib") list(APPEND platforms msysrt_g++) +list(APPEND langs CXX) # g77 dummy.f -v set(msys2rt_g77_text "Configured with: ... LD=/opt/gcc-tools/bin/ld.exe /usr/lib/gcc/i686-pc-msys/6.4.0/collect2.exe -Bdynamic --dll-search-prefix=msys- -u ___register_frame_info -u ___deregister_frame_info /usr/lib/gcc/i686-pc-msys/6.4.0/../../../crt0.o /usr/lib/gcc/i686-pc-msys/6.4.0/crtbegin.o -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0 -L/usr/lib/gcc/i686-pc-msys/6.4.0/../../.. /home/user/AppData/Local/Temp/ccqRWKWg.o -lgfortranbegin -lgfortran -lgcc_s -lgcc_s -lgcc -lmsys-2.0 -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc_s -lgcc_s -lgcc /usr/lib/gcc/i686-pc-msys/6.4.0/crtend.o") set(msys2rt_g77_libs "stdc++;msys-2.0;user32;kernel32;advapi32;shell32") set(msys2rt_g77_dirs "/usr/lib/gcc/i686-pc-msys/6.4.0;/usr/lib") list(APPEND platforms msysrt_g77) +list(APPEND langs Fortran) #----------------------------------------------------------------------------- # MSYS2-mingw @@ -490,18 +550,21 @@ set(msys2_gcc_text " C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/c set(msys2_gcc_libs "mingw32;gcc;moldname;mingwex;pthread;advapi32;shell32;user32;kernel32;mingw32;gcc;moldname;mingwex") set(msys2_gcc_dirs "C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/7.2.0;C:/msys64/mingw64/lib/gcc;C:/msys64/mingw64/x86_64-w64-mingw32/lib;C:/msys64/mingw64/lib") list(APPEND platforms msys2_gcc) +list(APPEND langs C) # g++ dummy.cxx -v set(msys2_g++_text " C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/collect2.exe -plugin C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/liblto_plugin-0.dll -plugin-opt=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/lto-wrapper.exe -plugin-opt=-fresolution=C:/msys64/tmp/ccJQgvbN.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lpthread -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -m i386pep -Bdynamic C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtbegin.o -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0 -LC:/msys64/mingw64/bin/../lib/gcc -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../.. C:/msys64/tmp/ccqPpuVS.o -lstdc++ -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/default-manifest.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtend.o") set(msys2_g++_libs "stdc++;mingw32;gcc_s;gcc;moldname;mingwex;pthread;advapi32;shell32;user32;kernel32;mingw32;gcc_s;gcc;moldname;mingwex") set(msys2_g++_dirs "C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/7.2.0;C:/msys64/mingw64/lib/gcc;C:/msys64/mingw64/x86_64-w64-mingw32/lib;C:/msys64/mingw64/lib") list(APPEND platforms msys2_g++) +list(APPEND langs CXX) # gfortran dummy.f90 -v set(msys2_gfortran_text " C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/collect2.exe -plugin C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/liblto_plugin-0.dll -plugin-opt=C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/lto-wrapper.exe -plugin-opt=-fresolution=C:/msys64/tmp/cczOKIDy.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lquadmath -plugin-opt=-pass-through=-lm -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -plugin-opt=-pass-through=-lpthread -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt -m i386pep -Bdynamic C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/crt2.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtbegin.o -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0 -LC:/msys64/mingw64/bin/../lib/gcc -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib -LC:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../.. C:/msys64/tmp/ccyXuCgD.o -lgfortran -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt -lquadmath -lm -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt -lpthread -ladvapi32 -lshell32 -luser32 -lkernel32 -lmingw32 -lgcc_s -lgcc -lmoldname -lmingwex -lmsvcrt C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/../../../../x86_64-w64-mingw32/lib/../lib/default-manifest.o C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.2.0/crtend.o") set(msys2_gfortran_libs "gfortran;mingw32;gcc_s;gcc;moldname;mingwex;quadmath;m;mingw32;gcc_s;gcc;moldname;mingwex;pthread;advapi32;shell32;user32;kernel32;mingw32;gcc_s;gcc;moldname;mingwex") set(msys2_gfortran_dirs "C:/msys64/mingw64/lib/gcc/x86_64-w64-mingw32/7.2.0;C:/msys64/mingw64/lib/gcc;C:/msys64/mingw64/x86_64-w64-mingw32/lib;C:/msys64/mingw64/lib") list(APPEND platforms msys2_gfortran) +list(APPEND langs Fortran) #----------------------------------------------------------------------------- # MSVC from NVIDIA CUDA @@ -510,6 +573,18 @@ set(nvcc_msvc_text [[cuda-fake-ld cl.exe -nologo "tmp/a_dlink.obj" "tmp/CMakeCUD set(nvcc_msvc_libs "cudadevrt.lib;cudart_static.lib") set(nvcc_msvc_dirs "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/lib/x64") list(APPEND platforms nvcc_msvc) +list(APPEND langs CUDA) + +#----------------------------------------------------------------------------- +# MSVC from NVIDIA CUDA custom compiler + +set(nvcc_msvc_cl_text [[cuda-fake-ld cl -nologo "tmp/a_dlink.obj" "tmp/CMakeCUDACompilerId.obj" -link -INCREMENTAL:NO "/LIBPATH:C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/bin/../lib/x64" cudadevrt.lib cudart_static.lib -Fe"a.exe"]]) +set(nvcc_msvc_cl_libs "cudadevrt.lib;cudart_static.lib") +set(nvcc_msvc_cl_dirs "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v8.0/lib/x64") +set(nvcc_msvc_cl_compiler_id NVIDIA) +set(nvcc_msvc_cl_compiler_sim_id MSVC) +list(APPEND platforms nvcc_msvc_cl) +list(APPEND langs CUDA) #----------------------------------------------------------------------------- # PGI on Windows @@ -527,6 +602,7 @@ set(windows_pgf95_startfile "pgimain[mx][xpt]+[.]obj") set(windows_pgf95_libs "libpgmp;pg;libpgf90rtl;libpgf90;libpgf90_rpm1;libpgf902;libpgf90rtl;libpgftnrtl;libpgc14;libnspgc;legacy_stdio_definitions;oldnames") set(windows_pgf95_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib") list(APPEND platforms windows_pgf95) +list(APPEND langs Fortran) # pgf77 dummy.f77 -v set(windows_pgf77_text [[Writing to file C:\temp\pgf776eC42buYRoCNJk.lnk @@ -537,6 +613,7 @@ set(windows_pgf77_startfile "pgimain[mx][xpt]+[.]obj") set(windows_pgf77_libs "libpgmp;libpgftnrtl;libpgc14;libnspgc;legacy_stdio_definitions;oldnames") set(windows_pgf77_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib") list(APPEND platforms windows_pgf77) +list(APPEND langs Fortran) # pgcc dummy.c -v set(windows_pgcc_text [[Writing to file C:\temp\pgcc6esqW26_ZNKyL.lnk @@ -547,6 +624,7 @@ set(windows_pgcc_startfile "pgimain[mx][xpt]+[.]obj") set(windows_pgcc_libs "libpgmp;libpgc14;libnspgc;legacy_stdio_definitions;oldnames") set(windows_pgcc_dirs "X:/NOT-PROGRAM-FILES-86/Microsoft Visual Studio 14.0/VC/Lib/AMD64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/ucrt/x64;X:/NOT-PROGRAM-FILES-86/Windows Kits/10/Lib/10.0.15063.0/um/x64;X:/NOT-PROGRAM-FILES/PGICE/win64/17.4/lib") list(APPEND platforms windows_pgcc) +list(APPEND langs C) endif() @@ -554,13 +632,20 @@ endif() # Test parsing for all above examples. set(CMAKE_LINKER "not-a-linker[]().*+^$?") -foreach(p IN LISTS platforms) +foreach(p lang IN ZIP_LISTS platforms langs) if(DEFINED ${p}_startfile) set(CMAKE_LINK_STARTFILE "${${p}_startfile}") else() unset(CMAKE_LINK_STARTFILE) endif() - cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}") + if(DEFINED ${p}_compiler_id) + set(CMAKE_${lang}_ID ${${p}_compiler_id}) + endif() + if(DEFINED ${p}_compiler_sim_id) + set(CMAKE_${lang}_SIMULATE_ID ${${p}_compiler_sim_id}) + endif() + + cmake_parse_implicit_link_info("${${p}_text}" libs dirs fwks log "${${p}_obj_regex}" LANGUAGE ${lang}) foreach(v libs dirs fwks) if(DEFINED "${p}_${v}" AND NOT "${${v}}" STREQUAL "${${p}_${v}}") diff --git a/Tests/CTestCoverageCollectGCOV/test.cmake.in b/Tests/CTestCoverageCollectGCOV/test.cmake.in index a36f374..7c7a3e5 100644 --- a/Tests/CTestCoverageCollectGCOV/test.cmake.in +++ b/Tests/CTestCoverageCollectGCOV/test.cmake.in @@ -34,9 +34,10 @@ set(expected_out # then back to relative to get them in canonical form (or maybe this is a bug # in how the tarball is generated?) function(to_relative_paths real_paths paths) + file(REAL_PATH "${CTEST_BINARY_DIRECTORY}" base) foreach(file ${paths}) - file(REAL_PATH "${file}" real_path BASE_DIRECTORY "${CTEST_BINARY_DIRECTORY}") - file(RELATIVE_PATH relative_path "${CTEST_BINARY_DIRECTORY}" "${real_path}") + file(REAL_PATH "${file}" real_path BASE_DIRECTORY "${base}") + file(RELATIVE_PATH relative_path "${base}" "${real_path}") list(APPEND local_real_paths "${relative_path}") message(DEBUG "${file} -> ${real_path} -> ${relative_path}") endforeach() diff --git a/Tests/CTestTestFdSetSize/sleep.c b/Tests/CTestTestFdSetSize/sleep.c index 2fb6490..d55cec6 100644 --- a/Tests/CTestTestFdSetSize/sleep.c +++ b/Tests/CTestTestFdSetSize/sleep.c @@ -1,7 +1,11 @@ #if defined(_WIN32) # include <windows.h> -#else +#elif _XOPEN_SOURCE >= 500 || defined(_ALL_SOURCE) # include <unistd.h> +#else +# include <time.h> + +# include <sys/select.h> #endif /* sleeps for 0.1 second */ @@ -9,8 +13,14 @@ int main(int argc, char** argv) { #if defined(_WIN32) Sleep(100); -#else +#elif _XOPEN_SOURCE >= 500 || defined(_ALL_SOURCE) usleep(100 * 1000); +#else + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100 * 1000; + + select(0, NULL, NULL, NULL, &tv); #endif return 0; } diff --git a/Tests/CTestUpdateCommon.cmake b/Tests/CTestUpdateCommon.cmake index 0f8ec8e..467b41a 100644 --- a/Tests/CTestUpdateCommon.cmake +++ b/Tests/CTestUpdateCommon.cmake @@ -73,7 +73,7 @@ function(check_updates build) string(REGEX REPLACE "${rev_regex}" "\\1" element "${r}") set(element_${element} 1) endforeach() - foreach(element ${rev_elements}) + foreach(element IN LISTS rev_elements) if(NOT element_${element}) list(APPEND MISSING "global <${element}> element") endif() @@ -85,7 +85,7 @@ function(check_updates build) if(MISSING) # List the missing entries string(APPEND MSG "Update.xml is missing expected entries:\n") - foreach(f ${MISSING}) + foreach(f IN LISTS MISSING) string(APPEND MSG " ${f}\n") endforeach() else() @@ -97,7 +97,7 @@ function(check_updates build) if(EXTRA) # List the extra entries string(APPEND MSG "Update.xml has extra unexpected entries:\n") - foreach(f ${EXTRA}) + foreach(f IN LISTS EXTRA) string(APPEND MSG " ${f}\n") endforeach() else() diff --git a/Tests/CTestUpdateP4.cmake.in b/Tests/CTestUpdateP4.cmake.in index 8a99e67..2ac01e2 100644 --- a/Tests/CTestUpdateP4.cmake.in +++ b/Tests/CTestUpdateP4.cmake.in @@ -109,7 +109,7 @@ list(APPEND P4CMD ${P4_CLIENT}) message("Adding files to repository") file(GLOB_RECURSE files ${TOP}/user-source/*) -foreach(filename ${files}) +foreach(filename IN LISTS files) run_child( WORKING_DIRECTORY ${TOP}/user-source COMMAND ${P4CMD} add ${filename} @@ -140,14 +140,14 @@ run_child( # Make changes in the working tree. message("Changing content...") update_content(user-source files_added files_removed dirs_added) -foreach(filename ${files_added}) +foreach(filename IN LISTS files_added) message("add: ${filename}") run_child( WORKING_DIRECTORY ${TOP}/user-source COMMAND ${P4CMD} add ${TOP}/user-source/${filename} ) endforeach() -foreach(filename ${files_removed}) +foreach(filename IN LISTS files_removed) run_child( WORKING_DIRECTORY ${TOP}/user-source COMMAND ${P4CMD} delete ${TOP}/user-source/${filename} diff --git a/Tests/CheckSourceTree/CMakeLists.txt b/Tests/CheckSourceTree/CMakeLists.txt new file mode 100644 index 0000000..3abc6a9 --- /dev/null +++ b/Tests/CheckSourceTree/CMakeLists.txt @@ -0,0 +1,6 @@ +add_test(NAME CMake.CheckSourceTree + COMMAND ${CMAKE_CMAKE_COMMAND} -D GIT_EXECUTABLE=${GIT_EXECUTABLE} + -D CMake_SOURCE_DIR=${CMake_SOURCE_DIR} + -P ${CMAKE_CURRENT_LIST_DIR}/check.cmake + ) +set_property(TEST CMake.CheckSourceTree PROPERTY RUN_SERIAL 1) diff --git a/Tests/CheckSourceTree/check.cmake b/Tests/CheckSourceTree/check.cmake new file mode 100644 index 0000000..c2e3529 --- /dev/null +++ b/Tests/CheckSourceTree/check.cmake @@ -0,0 +1,22 @@ +# Give Git access to the real home directory to get user's settings. +if(DEFINED ENV{CTEST_REAL_HOME}) + set(ENV{HOME} "$ENV{CTEST_REAL_HOME}") +endif() + +execute_process( + COMMAND "${GIT_EXECUTABLE}" status + WORKING_DIRECTORY "${CMake_SOURCE_DIR}" + OUTPUT_VARIABLE output + ERROR_VARIABLE output + RESULT_VARIABLE result + ) +string(REPLACE "\n" "\n " output " ${output}") +if(NOT result EQUAL 0) + message(FATAL_ERROR "'git status' failed (${result}):\n${output}") +endif() + +if(output MATCHES "\n[ \t#]*(Changes |new file:|modified:|Untracked )") + message(FATAL_ERROR "The source tree is not clean. 'git status' reports:\n${output}") +endif() + +message(STATUS "The source tree is clean.") diff --git a/Tests/CheckSwift.cmake b/Tests/CheckSwift.cmake index fcbae7e..099c298 100644 --- a/Tests/CheckSwift.cmake +++ b/Tests/CheckSwift.cmake @@ -14,6 +14,7 @@ if(NOT DEFINED CMAKE_Swift_COMPILER) project(CheckSwift Swift) file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" \"set(CMAKE_Swift_COMPILER \\\"\${CMAKE_Swift_COMPILER}\\\")\\n\" + \"set(CMAKE_Swift_COMPILER_VERSION \\\"\${CMAKE_Swift_COMPILER_VERSION}\\\")\\n\" \"set(CMAKE_Swift_FLAGS \\\"\${CMAKE_Swift_FLAGS}\\\")\\n\") ") @@ -54,6 +55,7 @@ file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\" message(STATUS "${_desc} - ${CMAKE_Swift_COMPILER}") set(CMAKE_Swift_COMPILER "${CMAKE_Swift_COMPILER}" CACHE FILEPATH "Swift compiler") + set(CMAKE_Swift_COMPILER_VERSION "${CMAKE_Swift_COMPILER_VERSION}" CACHE FILEPATH "Swift compiler version") set(CMAKE_Swift_FLAGS "${CMAKE_Swift_FLAGS}" CACHE STRING "Swift flags") mark_as_advanced(CMAKE_Swift_COMPILER) diff --git a/Tests/CompileFeatures/CMakeLists.txt b/Tests/CompileFeatures/CMakeLists.txt index c6d1e8a..f3d3a73 100644 --- a/Tests/CompileFeatures/CMakeLists.txt +++ b/Tests/CompileFeatures/CMakeLists.txt @@ -356,6 +356,7 @@ else() HAVE_CXX_STD_17=$<COMPILE_FEATURES:cxx_std_17> HAVE_CXX_STD_20=$<COMPILE_FEATURES:cxx_std_20> HAVE_CXX_STD_23=$<COMPILE_FEATURES:cxx_std_23> + HAVE_CXX_STD_26=$<COMPILE_FEATURES:cxx_std_26> ) endif() diff --git a/Tests/CompileFeatures/genex_test.cpp b/Tests/CompileFeatures/genex_test.cpp index 9c3910e..048f3de 100644 --- a/Tests/CompileFeatures/genex_test.cpp +++ b/Tests/CompileFeatures/genex_test.cpp @@ -27,6 +27,9 @@ # if HAVE_CXX_STD_23 && !defined(ALLOW_LATER_STANDARDS) # error HAVE_CXX_STD_23 is true with CXX_STANDARD == 11 # endif +# if HAVE_CXX_STD_26 && !defined(ALLOW_LATER_STANDARDS) +# error HAVE_CXX_STD_26 is true with CXX_STANDARD == 11 +# endif #endif #if !HAVE_OVERRIDE_CONTROL diff --git a/Tests/Complex/CMakeLists.txt b/Tests/Complex/CMakeLists.txt index 5df22d2..9493a2f 100644 --- a/Tests/Complex/CMakeLists.txt +++ b/Tests/Complex/CMakeLists.txt @@ -5,6 +5,14 @@ cmake_minimum_required(VERSION 2.4) cmake_policy(SET CMP0054 NEW) project (Complex) +# Inform the test if the debug configuration is getting built. +string(APPEND CMAKE_C_FLAGS_RELEASE " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_C_FLAGS_MINSIZEREL " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DCOMPLEX_NDEBUG") + # Test that renaming a built-in works when configured multiple times. message("message") function(message) diff --git a/Tests/Complex/Executable/complex.cxx b/Tests/Complex/Executable/complex.cxx index 49e97d5..67a1645 100644 --- a/Tests/Complex/Executable/complex.cxx +++ b/Tests/Complex/Executable/complex.cxx @@ -62,7 +62,7 @@ void cmPassed(const char* Message, const char* m2 = "") # error This is a problem. Looks like ADD_DEFINITIONS and REMOVE_DEFINITIONS does not work #endif -#if defined(NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE) +#if defined(COMPLEX_NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE) # error Per-configuration directory-level definition not inherited. #endif diff --git a/Tests/ComplexOneConfig/CMakeLists.txt b/Tests/ComplexOneConfig/CMakeLists.txt index 5a4134d..e4fdc68 100644 --- a/Tests/ComplexOneConfig/CMakeLists.txt +++ b/Tests/ComplexOneConfig/CMakeLists.txt @@ -5,6 +5,14 @@ cmake_minimum_required(VERSION 2.4) cmake_policy(SET CMP0054 NEW) project (Complex) +# Inform the test if the debug configuration is getting built. +string(APPEND CMAKE_C_FLAGS_RELEASE " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_C_FLAGS_MINSIZEREL " -DCOMPLEX_NDEBUG") +string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DCOMPLEX_NDEBUG") + # Try setting a new policy. The IF test is for coverage. if(POLICY CMP0003) cmake_policy(SET CMP0003 NEW) diff --git a/Tests/ComplexOneConfig/Executable/complex.cxx b/Tests/ComplexOneConfig/Executable/complex.cxx index 54c18f4..097668b 100644 --- a/Tests/ComplexOneConfig/Executable/complex.cxx +++ b/Tests/ComplexOneConfig/Executable/complex.cxx @@ -62,7 +62,7 @@ void cmPassed(const char* Message, const char* m2 = "") # error This is a problem. Looks like ADD_DEFINITIONS and REMOVE_DEFINITIONS does not work #endif -#if defined(NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE) +#if defined(COMPLEX_NDEBUG) && !defined(CMAKE_IS_FUN_IN_RELEASE_MODE) # error Per-configuration directory-level definition not inherited. #endif diff --git a/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt b/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt index 97670e3..447e137 100644 --- a/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt +++ b/Tests/Cuda/SeparableCompCXXOnly/CMakeLists.txt @@ -1,3 +1,6 @@ -project(SeparableCompCXXOnly LANGUAGES CXX CUDA) +# Set CMAKE_CUDA_SEPARABLE_COMPILATION before `project` +# so we verify that compiler/linker verbose extraction +# works as required when a `dlink` is part of it set(CMAKE_CUDA_SEPARABLE_COMPILATION ON) +project(SeparableCompCXXOnly LANGUAGES CXX CUDA) add_executable(SeparableCompCXXOnly main.cpp) diff --git a/Tests/CudaOnly/CMakeLists.txt b/Tests/CudaOnly/CMakeLists.txt index aa4755d..091872d 100644 --- a/Tests/CudaOnly/CMakeLists.txt +++ b/Tests/CudaOnly/CMakeLists.txt @@ -7,7 +7,6 @@ endmacro () add_cuda_test_macro(CudaOnly.Architecture Architecture) add_cuda_test_macro(CudaOnly.ArchSpecial CudaOnlyArchSpecial) add_cuda_test_macro(CudaOnly.CompileFlags CudaOnlyCompileFlags) - add_cuda_test_macro(CudaOnly.EnableStandard CudaOnlyEnableStandard) add_cuda_test_macro(CudaOnly.ExportPTX CudaOnlyExportPTX) add_cuda_test_macro(CudaOnly.SharedRuntimePlusToolkit CudaOnlySharedRuntimePlusToolkit) @@ -28,6 +27,19 @@ if(CMake_TEST_CUDA AND NOT CMake_TEST_CUDA STREQUAL "Clang") add_cuda_test_macro(CudaOnly.GPUDebugFlag CudaOnlyGPUDebugFlag) endif() +# The CUDA only ships the shared version of the toolkit libraries +# on windows +if(NOT WIN32) + add_cuda_test_macro(CudaOnly.StaticRuntimePlusToolkit CudaOnlyStaticRuntimePlusToolkit) +endif() + +add_cuda_test_macro(CudaOnly.DeviceLTO CudaOnlyDeviceLTO) + +if(MSVC) + # Tests for features that only work with MSVC + add_cuda_test_macro(CudaOnly.PDB CudaOnlyPDB) +endif() + add_test(NAME CudaOnly.DontResolveDeviceSymbols COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --build-and-test @@ -41,16 +53,6 @@ add_test(NAME CudaOnly.DontResolveDeviceSymbols COMMAND set_property(TEST "CudaOnly.DontResolveDeviceSymbols" APPEND PROPERTY LABELS "CUDA") -# The CUDA only ships the shared version of the toolkit libraries -# on windows -if(NOT WIN32) - add_cuda_test_macro(CudaOnly.StaticRuntimePlusToolkit CudaOnlyStaticRuntimePlusToolkit) -endif() - -if(MSVC) - add_cuda_test_macro(CudaOnly.PDB CudaOnlyPDB) -endif() - add_test(NAME CudaOnly.RuntimeControls COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --build-and-test diff --git a/Tests/CudaOnly/DeviceLTO/CMakeLists.txt b/Tests/CudaOnly/DeviceLTO/CMakeLists.txt new file mode 100644 index 0000000..653b35d --- /dev/null +++ b/Tests/CudaOnly/DeviceLTO/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 3.18) +project(DeviceLTO CUDA) + +# Goal: +# Verify that we correctly compile with device LTO +# Verify that device LTO requirements are propagated to +# the final device link line + +add_library(CUDA_dlto STATIC file1.cu file2.cu file3.cu) +add_executable(CudaOnlyDeviceLTO main.cu) + +set_target_properties(CUDA_dlto + PROPERTIES + CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES_ALL}" + CUDA_SEPARABLE_COMPILATION ON + POSITION_INDEPENDENT_CODE ON) + +set_target_properties(CudaOnlyDeviceLTO + PROPERTIES + CUDA_SEPARABLE_COMPILATION ON + CUDA_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES_ALL}" + ) + +target_link_libraries(CudaOnlyDeviceLTO PRIVATE CUDA_dlto) + +include(CheckIPOSupported) +check_ipo_supported(LANGUAGES CUDA RESULT ipo_supported) +if(ipo_supported) + set_target_properties(CUDA_dlto + PROPERTIES + INTERPROCEDURAL_OPTIMIZATION ON) + + # When non-LTO variants (i.e. virtual) are built together with LTO ones the + # linker warns about missing device LTO for the virtual architectures. + # Ignore these warnings. + target_link_options(CudaOnlyDeviceLTO PRIVATE "$<DEVICE_LINK:-w>") +endif() diff --git a/Tests/CudaOnly/DeviceLTO/file1.cu b/Tests/CudaOnly/DeviceLTO/file1.cu new file mode 100644 index 0000000..703927c --- /dev/null +++ b/Tests/CudaOnly/DeviceLTO/file1.cu @@ -0,0 +1,17 @@ +#ifdef _WIN32 +# define EXPORT __declspec(dllexport) +#else +# define EXPORT +#endif + +extern __device__ int file2_func(int); +void __global__ kernel(int x) +{ + file2_func(x); +} + +EXPORT int launch_kernel(int x) +{ + kernel<<<1, 1>>>(x); + return x; +} diff --git a/Tests/CudaOnly/DeviceLTO/file2.cu b/Tests/CudaOnly/DeviceLTO/file2.cu new file mode 100644 index 0000000..73d6468 --- /dev/null +++ b/Tests/CudaOnly/DeviceLTO/file2.cu @@ -0,0 +1,5 @@ +extern __device__ int file3_func(int); +int __device__ file2_func(int x) +{ + return x + file3_func(x); +} diff --git a/Tests/CudaOnly/DeviceLTO/file3.cu b/Tests/CudaOnly/DeviceLTO/file3.cu new file mode 100644 index 0000000..235ac06 --- /dev/null +++ b/Tests/CudaOnly/DeviceLTO/file3.cu @@ -0,0 +1,4 @@ +int __device__ file3_func(int x) +{ + return x * x * x; +} diff --git a/Tests/CudaOnly/DeviceLTO/main.cu b/Tests/CudaOnly/DeviceLTO/main.cu new file mode 100644 index 0000000..8ef4873 --- /dev/null +++ b/Tests/CudaOnly/DeviceLTO/main.cu @@ -0,0 +1,62 @@ +#include <iostream> + +#include "cuda.h" + +#ifdef _WIN32 +# define IMPORT __declspec(dllimport) +#else +# define IMPORT +#endif + +IMPORT int launch_kernel(int x); + +int choose_cuda_device() +{ + int nDevices = 0; + cudaError_t err = cudaGetDeviceCount(&nDevices); + if (err != cudaSuccess) { + std::cerr << "Failed to retrieve the number of CUDA enabled devices" + << std::endl; + return 1; + } + for (int i = 0; i < nDevices; ++i) { + cudaDeviceProp prop; + cudaError_t err = cudaGetDeviceProperties(&prop, i); + if (err != cudaSuccess) { + std::cerr << "Could not retrieve properties from CUDA device " << i + << std::endl; + return 1; + } + std::cout << "prop.major: " << prop.major << std::endl; + err = cudaSetDevice(i); + if (err != cudaSuccess) { + std::cout << "Could not select CUDA device " << i << std::endl; + } else { + return 0; + } + } + + std::cout << "Could not find a CUDA enabled card" << std::endl; + + return 1; +} + +int main() +{ + int ret = choose_cuda_device(); + if (ret) { + return 0; + } + + cudaError_t err; + launch_kernel(1); + err = cudaGetLastError(); + if (err != cudaSuccess) { + std::cerr << "launch_kernel: kernel launch should have passed.\n " + "Error message: " + << cudaGetErrorString(err) << std::endl; + return 1; + } + + return 0; +} diff --git a/Tests/EnforceConfig.cmake.in b/Tests/EnforceConfig.cmake.in index 7c6f76a..7722d7d 100644 --- a/Tests/EnforceConfig.cmake.in +++ b/Tests/EnforceConfig.cmake.in @@ -10,7 +10,7 @@ if(NOT CTEST_CONFIGURATION_TYPE) set(CTEST_CMD "@CMAKE_CTEST_COMMAND@@CMAKE_EXECUTABLE_SUFFIX@") get_filename_component(CTEST_DIR "${CTEST_CMD}" PATH) get_filename_component(CTEST_EXE "${CTEST_CMD}" NAME) - foreach(cfg Release Debug MinSizeRel RelWithDebInfo) + foreach(cfg IN ITEMS Release Debug MinSizeRel RelWithDebInfo) if(NOT CTEST_CONFIGURATION_TYPE) if(EXISTS "${CTEST_DIR}/${cfg}/${CTEST_EXE}") set(CTEST_CONFIGURATION_TYPE ${cfg}) @@ -36,4 +36,4 @@ unset(ENV{CMAKE_GENERATOR_TOOLSET}) unset(ENV{CMAKE_EXPORT_COMPILE_COMMANDS}) @TEST_HOME_ENV_CODE@ -@TEST_WARN_VS10_CODE@ +@TEST_WARN_VS11_CODE@ diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index c9e41f5..6f19c13 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -155,6 +155,15 @@ target_include_directories(testInterfaceIncludeUser "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/testInterfaceIncludeUser>" ) set_property(TARGET testInterfaceIncludeUser PROPERTY IMPORTED_NO_SYSTEM 1) + +add_library(testInterfaceIncludeUser2 INTERFACE) +target_include_directories(testInterfaceIncludeUser2 + INTERFACE + "$<INSTALL_INTERFACE:include/testInterfaceIncludeUser>" + "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/testInterfaceIncludeUser>" +) +set_property(TARGET testInterfaceIncludeUser2 PROPERTY EXPORT_NO_SYSTEM 1) + install( FILES "${CMAKE_CURRENT_SOURCE_DIR}/include/testInterfaceIncludeUser/testInterfaceInclude.h" @@ -562,6 +571,7 @@ install( TopDirLib SubDirLinkA systemlib testInterfaceIncludeUser + testInterfaceIncludeUser2 EXPORT exp RUNTIME DESTINATION $<1:bin>$<0:/wrong> LIBRARY DESTINATION $<1:lib>$<0:/wrong> NAMELINK_SKIP @@ -622,6 +632,7 @@ export(TARGETS testExe1 testLib1 testLib2 testLib3 TopDirLib SubDirLinkA systemlib testInterfaceIncludeUser + testInterfaceIncludeUser2 NAMESPACE bld_ FILE ExportBuildTree.cmake ) diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 272c7a9..5bafdf8 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -75,6 +75,10 @@ add_library(imp_testInterfaceInclude1 STATIC imp_testInterfaceInclude1.c) target_include_directories(imp_testInterfaceInclude1 SYSTEM PRIVATE testInterfaceIncludeSystem) target_link_libraries(imp_testInterfaceInclude1 PRIVATE exp_testInterfaceIncludeUser) +add_library(imp_testInterfaceInclude1b STATIC imp_testInterfaceInclude1.c) +target_include_directories(imp_testInterfaceInclude1b SYSTEM PRIVATE testInterfaceIncludeSystem) +target_link_libraries(imp_testInterfaceInclude1b PRIVATE exp_testInterfaceIncludeUser2) + add_executable(imp_UseSharedLibWithHelper1 ../../../InterfaceLinkLibrariesDirect/UseSharedLibWithHelper.c) target_link_libraries(imp_UseSharedLibWithHelper1 PRIVATE exp_testSharedLibWithHelper testSharedLibHelperExclude) @@ -122,9 +126,13 @@ target_link_libraries(imp_testExe1b bld_testStaticLibWithPlugin ) -add_library(imp_testInterfaceInclude1b STATIC imp_testInterfaceInclude1.c) -target_include_directories(imp_testInterfaceInclude1b SYSTEM PRIVATE testInterfaceIncludeSystem) -target_link_libraries(imp_testInterfaceInclude1b PRIVATE bld_testInterfaceIncludeUser) +add_library(imp_testInterfaceInclude1c STATIC imp_testInterfaceInclude1.c) +target_include_directories(imp_testInterfaceInclude1c SYSTEM PRIVATE testInterfaceIncludeSystem) +target_link_libraries(imp_testInterfaceInclude1c PRIVATE bld_testInterfaceIncludeUser) + +add_library(imp_testInterfaceInclude1d STATIC imp_testInterfaceInclude1.c) +target_include_directories(imp_testInterfaceInclude1d SYSTEM PRIVATE testInterfaceIncludeSystem) +target_link_libraries(imp_testInterfaceInclude1d PRIVATE bld_testInterfaceIncludeUser2) add_custom_target(check_testLib1_genex ALL COMMAND ${CMAKE_COMMAND} -DtestLib1=$<TARGET_FILE:exp_testLib1> diff --git a/Tests/ExternalProject/CMakeLists.txt b/Tests/ExternalProject/CMakeLists.txt index e4c6c66..81d31e7 100644 --- a/Tests/ExternalProject/CMakeLists.txt +++ b/Tests/ExternalProject/CMakeLists.txt @@ -45,7 +45,11 @@ if(NOT DEFINED EP_TEST_HG OR EP_TEST_HG) find_package(Hg) endif() if(NOT DEFINED EP_TEST_HG AND Hg_FOUND) - set(EP_TEST_HG 1) + # Check if hg executable is working + execute_process(COMMAND "${HG_EXECUTABLE}" --version OUTPUT_QUIET ERROR_QUIET RESULT_VARIABLE HG_RV) + if(HG_RV EQUAL 0) + set(EP_TEST_HG 1) + endif() endif() message(STATUS "EP_TEST_CVS='${EP_TEST_CVS}' CVS_EXECUTABLE='${CVS_EXECUTABLE}'") diff --git a/Tests/FindOpenAL/CMakeLists.txt b/Tests/FindOpenAL/CMakeLists.txt new file mode 100644 index 0000000..fc4803e --- /dev/null +++ b/Tests/FindOpenAL/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindOpenAL.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindOpenAL/Test" + "${CMake_BINARY_DIR}/Tests/FindOpenAL/Test" + ${build_generator_args} + --build-project TestFindOpenAL + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/FindOpenAL/Test/CMakeLists.txt b/Tests/FindOpenAL/Test/CMakeLists.txt new file mode 100644 index 0000000..fa3e263 --- /dev/null +++ b/Tests/FindOpenAL/Test/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.21) +project(TestFindOpenAL CXX) +include(CTest) + +find_package(OpenAL REQUIRED) + +add_executable(test_tgt main.cxx) +target_link_libraries(test_tgt OpenAL::OpenAL) +add_test(NAME test_tgt COMMAND test_tgt) + +add_executable(test_var main.cxx) +target_include_directories(test_var PRIVATE ${OPENAL_INCLUDE_DIR}) +target_link_libraries(test_var PRIVATE ${OPENAL_LIBRARY}) +add_test(NAME test_var COMMAND test_var) diff --git a/Tests/FindOpenAL/Test/main.cxx b/Tests/FindOpenAL/Test/main.cxx new file mode 100644 index 0000000..bb45faf --- /dev/null +++ b/Tests/FindOpenAL/Test/main.cxx @@ -0,0 +1,13 @@ +#include <AL/al.h> +#include <AL/alc.h> +#include <stdio.h> + +int main() +{ + /* Reference an AL symbol without requiring a context at runtime. */ + printf("&alGetString = %p\n", &alGetString); + + /* Reference an ALC symbol without requiring a context at runtime. */ + printf("&alcGetString = %p\n", &alcGetString); + return 0; +} diff --git a/Tests/FindOpenSP/CMakeLists.txt b/Tests/FindOpenSP/CMakeLists.txt new file mode 100644 index 0000000..26826d3 --- /dev/null +++ b/Tests/FindOpenSP/CMakeLists.txt @@ -0,0 +1,10 @@ +add_test(NAME FindOpenSP.Test COMMAND + ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindOpenSP/Test" + "${CMake_BINARY_DIR}/Tests/FindOpenSP/Test" + ${build_generator_args} + --build-project TestFindOpenSP + --build-options ${build_options} + --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION> + ) diff --git a/Tests/FindOpenSP/Test/CMakeLists.txt b/Tests/FindOpenSP/Test/CMakeLists.txt new file mode 100644 index 0000000..d8992d9 --- /dev/null +++ b/Tests/FindOpenSP/Test/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.4) +project(TestFindOpenSP CXX) +include(CTest) + +find_package(OpenSP REQUIRED) + +add_definitions(-DSP_MULTI_BYTE="${OpenSP_MULTI_BYTE}") + +add_executable(test_tgt main.cxx) +target_link_libraries(test_tgt OpenSP::OpenSP) +add_test(NAME test_tgt COMMAND test_tgt) + +add_executable(test_var main.cxx) +target_include_directories(test_var PRIVATE ${OpenSP_INCLUDE_DIRS}) +target_link_libraries(test_var PRIVATE ${OpenSP_LIBRARIES}) +add_test(NAME test_var COMMAND test_var) diff --git a/Tests/FindOpenSP/Test/main.cxx b/Tests/FindOpenSP/Test/main.cxx new file mode 100644 index 0000000..ef8aa2c --- /dev/null +++ b/Tests/FindOpenSP/Test/main.cxx @@ -0,0 +1,55 @@ +#include <cassert> +#include <string> + +#include "ParserEventGeneratorKit.h" + +std::string CharStringtostring(const SGMLApplication::CharString source) +{ + // The CharString type might have multi-byte characters if SP_MULTI_BYTE was + // defined + std::string result; + result.resize(source.len); + for (size_t i = 0; i < source.len; i++) { + result[i] = static_cast<char>(source.ptr[i]); + } + return result; +} + +class OutlineApplication : public SGMLApplication +{ +public: + OutlineApplication() + : depth_(0) + { + } + void startElement(const StartElementEvent& event) + { + for (unsigned i = 0; i < depth_; i++) + parsedOutput += "\t"; + parsedOutput += CharStringtostring(event.gi); + depth_++; + } + void endElement(const EndElementEvent&) { depth_--; } + std::string parsedOutput; + +private: + unsigned depth_; +}; + +int main() +{ + std::string expectedOutput = "TESTDOC\tTESTELEMENT"; + char file_name[] = "test.sgml"; + char* files[] = { file_name, 0 }; + + ParserEventGeneratorKit parserKit; + EventGenerator* egp = parserKit.makeEventGenerator(1, files); + OutlineApplication app; + unsigned nErrors = egp->run(app); + + assert(nErrors == 0); + assert(app.parsedOutput.compare(expectedOutput) == 0); + + delete egp; + return 0; +} diff --git a/Tests/FindOpenSP/Test/test.sgml b/Tests/FindOpenSP/Test/test.sgml new file mode 100644 index 0000000..bbf0da6 --- /dev/null +++ b/Tests/FindOpenSP/Test/test.sgml @@ -0,0 +1,7 @@ + <!DOCTYPE TESTDOC [ +<!ELEMENT TESTDOC - - (TESTELEMENT)+> +<!ELEMENT TESTELEMENT - - (#PCDATA)> +]> +<TESTDOC> +<TESTELEMENT>Hello</TESTELEMENT> +</TESTDOC> diff --git a/Tests/FindPackageTest/CMakeLists.txt b/Tests/FindPackageTest/CMakeLists.txt index c25b2c3..e4143b9 100644 --- a/Tests/FindPackageTest/CMakeLists.txt +++ b/Tests/FindPackageTest/CMakeLists.txt @@ -20,7 +20,7 @@ find_package(OpenGL QUIET) find_package(NotAPackage QUIET) # Look for a package that has an advanced find module. -find_package(VTK QUIET) +find_package(Boost QUIET) add_executable(FindPackageTest FindPackageTest.cxx) diff --git a/Tests/FindVulkan/Test/CMakeLists.txt b/Tests/FindVulkan/Test/CMakeLists.txt index 42543ac..dfcfc15 100644 --- a/Tests/FindVulkan/Test/CMakeLists.txt +++ b/Tests/FindVulkan/Test/CMakeLists.txt @@ -7,7 +7,10 @@ set(components glslang shaderc_combined SPIRV-Tools + volk + dxc ) + if(APPLE) list(APPEND components MoltenVK) endif() @@ -75,6 +78,14 @@ if(APPLE) add_test(NAME test_tgt_MoltenVK COMMAND test_tgt_MoltenVK) endif() +add_executable(test_tgt_volk main-volk.cxx) +target_link_libraries(test_tgt_volk Vulkan::volk) +add_test(NAME test_tgt_volk COMMAND test_tgt_volk) + +add_executable(test_tgt_dxc_lib main-dxc_lib.cxx) +target_link_libraries(test_tgt_dxc_lib Vulkan::dxc_lib) +add_test(NAME test_tgt_dxc_lib COMMAND test_tgt_dxc_lib) + if(Vulkan_GLSLC_EXECUTABLE) add_test(NAME test_glslc COMMAND ${CMAKE_COMMAND} @@ -92,3 +103,12 @@ if(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE) -P "${CMAKE_CURRENT_LIST_DIR}/Run-glslangValidator.cmake" ) endif() + +if(Vulkan_dxc_EXECUTABLE) + add_test(NAME test_dxc_exe + COMMAND ${CMAKE_COMMAND} + "-DVULKAN_DXC_EXECUTABLE=${Vulkan_dxc_EXECUTABLE}" + "-DVULKAN_DXC_EXECUTABLE_TARGET=$<TARGET_FILE:Vulkan::dxc_exe>" + -P "${CMAKE_CURRENT_LIST_DIR}/Run-dxc_exe.cmake" + ) +endif() diff --git a/Tests/FindVulkan/Test/Run-dxc_exe.cmake b/Tests/FindVulkan/Test/Run-dxc_exe.cmake new file mode 100644 index 0000000..0d38855 --- /dev/null +++ b/Tests/FindVulkan/Test/Run-dxc_exe.cmake @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.12) + +function(run_dxc_exe exe exe_display) + execute_process(COMMAND ${exe} --help + OUTPUT_VARIABLE output + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE result + ) + + if(NOT result EQUAL 0) + message(SEND_ERROR "Result of ${exe_display} --help is ${result}, should be 0") + endif() + + if(NOT output MATCHES "^OVERVIEW: HLSL Compiler for ") + message(SEND_ERROR "Output of ${exe_display} --help is \"${output}\", should begin with \"OVERVIEW: HLSL Compiler for \"") + endif() +endfunction() + +run_dxc_exe("${VULKAN_DXC_EXECUTABLE}" "\${VULKAN_DXC_EXECUTABLE}") +run_dxc_exe("${VULKAN_DXC_EXECUTABLE_TARGET}" "Vulkan::dxc_exe") diff --git a/Tests/FindVulkan/Test/main-dxc_lib.cxx b/Tests/FindVulkan/Test/main-dxc_lib.cxx new file mode 100644 index 0000000..6ccb0de --- /dev/null +++ b/Tests/FindVulkan/Test/main-dxc_lib.cxx @@ -0,0 +1,23 @@ +#include <cstdio> + +#include "dxc/dxcapi.h" +#include "printf.h" + +int main() +{ + IDxcCompiler3* compiler; + DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); + + assert(compiler); + + IDxcVersionInfo* version; + compiler->QueryInterface(&version); + + uint32_t major, minor; + version->GetVersion(&major, &minor); + printf("DirectX Shader Compiler: %u.%u\n", major, minor); + version->Release(); + compiler->Release(); + + return 0; +} diff --git a/Tests/FindVulkan/Test/main-volk.cxx b/Tests/FindVulkan/Test/main-volk.cxx new file mode 100644 index 0000000..2ec9fb4 --- /dev/null +++ b/Tests/FindVulkan/Test/main-volk.cxx @@ -0,0 +1,14 @@ +#include <iostream> + +#include <volk/volk.h> + +int main() +{ + if (volkInitialize() != VK_SUCCESS) { + std::cout << "volk initialization success!" << std::endl; + } else { + std::cout << "volk initialization failure!" << std::endl; + } + + return 0; +} diff --git a/Tests/FortranModules/Submodules/CMakeLists.txt b/Tests/FortranModules/Submodules/CMakeLists.txt index ab8e0f9..783af7e 100644 --- a/Tests/FortranModules/Submodules/CMakeLists.txt +++ b/Tests/FortranModules/Submodules/CMakeLists.txt @@ -16,6 +16,7 @@ add_executable(submod main.f90 parent.f90 + obfuscated_parent.f90 child.f90 grandchild.f90 greatgrandchild.f90 diff --git a/Tests/FortranModules/Submodules/main.f90 b/Tests/FortranModules/Submodules/main.f90 index 3cd2989..67ffba8 100644 --- a/Tests/FortranModules/Submodules/main.f90 +++ b/Tests/FortranModules/Submodules/main.f90 @@ -1,7 +1,10 @@ program main use parent, only : child_function,grandchild_subroutine use parent, only : sibling_function,GreatGrandChild_subroutine + ! Using a module without postfix + use obfuscated_parent implicit none - if (child_function()) call grandchild_subroutine - if (sibling_function()) call GreatGrandChild_subroutine + if (child_function()) call grandchild_subroutine + if (sibling_function()) call GreatGrandChild_subroutine + if (child_function_obf()) call grandchild_subroutine_obf end program diff --git a/Tests/FortranModules/Submodules/obfuscated_parent.f90 b/Tests/FortranModules/Submodules/obfuscated_parent.f90 new file mode 100644 index 0000000..f3e68be --- /dev/null +++ b/Tests/FortranModules/Submodules/obfuscated_parent.f90 @@ -0,0 +1,33 @@ +! This module has two procedures from the "parent" module +! but it has different combinations 'module <word>' phrases +! in breaked lines for test of modules dependencies detection + +! Module declaration on breaked line with reminder +module & + obfuscated_parent; implicit none + + interface + + ! Boolean module function + module logical & + function child_function_obf() result(child_stuff) + end function + + ! Module subroutine + module subroutine & + grandchild_subroutine_obf() + end subroutine + + end interface + + contains + + module logical function child_function_obf() result(child_stuff) + child_stuff=.true. + end function + + module subroutine grandchild_subroutine_obf() + print *,"Test passed." + end subroutine + +end module obfuscated_parent diff --git a/Tests/FortranModules/test_module_main.f90 b/Tests/FortranModules/test_module_main.f90 index 6ac97fa..958d0a2 100644 --- a/Tests/FortranModules/test_module_main.f90 +++ b/Tests/FortranModules/test_module_main.f90 @@ -1,4 +1,4 @@ PROGRAM MAINF90 - USE TEST_MODULE + USE TEST_MODULE, only : TEST_MODULE_FUNCTION PRINT *,'Sum is',TEST_MODULE_FUNCTION(1., 2.) END PROGRAM MAINF90 diff --git a/Tests/FunctionTest/CMakeLists.txt b/Tests/FunctionTest/CMakeLists.txt index 6450447..0660d0f 100644 --- a/Tests/FunctionTest/CMakeLists.txt +++ b/Tests/FunctionTest/CMakeLists.txt @@ -51,7 +51,7 @@ track_find_variable(testvar is_changed) if ("${is_changed}" STREQUAL changed) pass("same argument name test") else () - pass("same argument name test") + fail("same argument name test" "Got: ${is_changed}") endif () include("Util.cmake") @@ -59,7 +59,7 @@ tester() if (tester_res STREQUAL "${CMAKE_CURRENT_LIST_FILE}") pass("CMAKE_CURRENT_LIST_FILE test") else () - pass("CMAKE_CURRENT_LIST_FILE test") + fail("CMAKE_CURRENT_LIST_FILE test" "Got: ${tester_res}") endif () diff --git a/Tests/IncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/CMakeLists.txt index bb4b92c..e82cea2 100644 --- a/Tests/IncludeDirectories/CMakeLists.txt +++ b/Tests/IncludeDirectories/CMakeLists.txt @@ -121,12 +121,66 @@ add_library(ordertest ordertest.cpp) target_include_directories(ordertest SYSTEM PUBLIC SystemIncludeDirectories/systemlib) target_include_directories(ordertest PUBLIC SystemIncludeDirectories/userlib) +# Test "IMPORTED_NO_SYSTEM" property and its interaction with "SYSTEM" add_library(ordertest2 ordertest.cpp) target_include_directories(ordertest2 SYSTEM PRIVATE SystemIncludeDirectories/systemlib) target_link_libraries(ordertest2 PRIVATE ordertest2_userlib) add_library(ordertest2_userlib INTERFACE IMPORTED) target_include_directories(ordertest2_userlib INTERFACE SystemIncludeDirectories/userlib) set_property(TARGET ordertest2_userlib PROPERTY IMPORTED_NO_SYSTEM 1) +get_property(system_prop_value TARGET ordertest2_userlib PROPERTY SYSTEM) +if (NOT system_prop_value) + message(SEND_ERROR "ordertest2_userlib SYSTEM property should be ON.") +endif() + +# Test "SYSTEM" property of non-imported libraries +add_library(ordertest3_systemlib INTERFACE) +target_include_directories(ordertest3_systemlib INTERFACE SystemIncludeDirectories/systemlib) +set_property(TARGET ordertest3_systemlib PROPERTY SYSTEM 1) +add_library(ordertest3_userlib INTERFACE) +target_include_directories(ordertest3_userlib INTERFACE SystemIncludeDirectories/userlib) +add_library(ordertest3 ordertest.cpp) +target_link_libraries(ordertest3 PRIVATE ordertest3_systemlib ordertest3_userlib) + +# Test "SYSTEM" property of imported libraries and its interaction with "IMPORTED_NO_SYSTEM" +add_library(ordertest4 ordertest.cpp) +target_include_directories(ordertest4 SYSTEM PRIVATE SystemIncludeDirectories/systemlib) +target_link_libraries(ordertest4 PRIVATE ordertest4_userlib) +add_library(ordertest4_userlib INTERFACE IMPORTED) +target_include_directories(ordertest4_userlib INTERFACE SystemIncludeDirectories/userlib) +set_property(TARGET ordertest4_userlib PROPERTY SYSTEM 0) +get_property(imported_no_system_prop_value TARGET ordertest4_userlib PROPERTY IMPORTED_NO_SYSTEM) +if (imported_no_system_prop_value) + message(SEND_ERROR "ordertest4_userlib IMPORTED_NO_SYSTEM property should be OFF.") +endif() + +# Test the interaction between "SYSTEM" and "INTERFACE_SYSTEM_INCLUDE_DIRECTORIES" +add_library(ordertest5_systemlib INTERFACE) +target_include_directories(ordertest5_systemlib SYSTEM INTERFACE SystemIncludeDirectories/systemlib) +# The default value of `SYSTEM` is already `OFF`. Here we explicitly set it again. +set_property(TARGET ordertest5_systemlib PROPERTY SYSTEM 0) +add_library(ordertest5_userlib INTERFACE) +target_include_directories(ordertest5_userlib INTERFACE SystemIncludeDirectories/userlib) +add_library(ordertest5 ordertest.cpp) +target_link_libraries(ordertest5 PRIVATE ordertest5_systemlib ordertest5_userlib) + +# Test that the include of imported executable is treated as system by default. +add_executable(ordertest6_systemexe IMPORTED) +target_include_directories(ordertest6_systemexe INTERFACE SystemIncludeDirectories/systemlib) +set_property(TARGET ordertest6_systemexe PROPERTY ENABLE_EXPORTS 1) +add_library(ordertest6_userlib INTERFACE) +target_include_directories(ordertest6_userlib INTERFACE SystemIncludeDirectories/userlib) +add_library(ordertest6 ordertest.cpp) +target_link_libraries(ordertest6 PRIVATE ordertest6_systemexe ordertest6_userlib) + +# Test that the include of imported executable is not treated as system if "SYSTEM" property is OFF. +add_library(ordertest7 ordertest.cpp) +target_include_directories(ordertest7 SYSTEM PRIVATE SystemIncludeDirectories/systemlib) +target_link_libraries(ordertest7 PRIVATE ordertest7_userexe) +add_library(ordertest7_userexe INTERFACE IMPORTED) +target_include_directories(ordertest7_userexe INTERFACE SystemIncludeDirectories/userlib) +set_property(TARGET ordertest7_userexe PROPERTY ENABLE_EXPORTS 1) +set_property(TARGET ordertest7_userexe PROPERTY SYSTEM 0) add_subdirectory(StandardIncludeDirectories) add_subdirectory(TargetIncludeDirectories) diff --git a/Tests/LoadCommand/CMakeCommands/cmTestCommand.c b/Tests/LoadCommand/CMakeCommands/cmTestCommand.c index af7b092..7176ebe 100644 --- a/Tests/LoadCommand/CMakeCommands/cmTestCommand.c +++ b/Tests/LoadCommand/CMakeCommands/cmTestCommand.c @@ -75,10 +75,10 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[]) info->CAPI->DisplaySatus(mf, info->CAPI->GetStartOutputDirectory(mf)); info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentDirectory(mf)); info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentOutputDirectory(mf)); - sprintf(buffer, "Cache version: %d.%d, CMake version: %d.%d", - info->CAPI->GetCacheMajorVersion(mf), - info->CAPI->GetCacheMinorVersion(mf), - info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf)); + snprintf( + buffer, sizeof(buffer), "Cache version: %d.%d, CMake version: %d.%d", + info->CAPI->GetCacheMajorVersion(mf), info->CAPI->GetCacheMinorVersion(mf), + info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf)); info->CAPI->DisplaySatus(mf, buffer); if (info->CAPI->CommandExists(mf, "SET")) { info->CAPI->DisplaySatus(mf, "Command SET exists"); @@ -91,10 +91,12 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[]) source_file = info->CAPI->CreateNewSourceFile(mf); cstr = info->CAPI->SourceFileGetSourceName(source_file); - sprintf(buffer, "Should be empty (source file name): [%s]", cstr); + snprintf(buffer, sizeof(buffer), "Should be empty (source file name): [%s]", + cstr); info->CAPI->DisplaySatus(mf, buffer); cstr = info->CAPI->SourceFileGetFullPath(source_file); - sprintf(buffer, "Should be empty (source file full path): [%s]", cstr); + snprintf(buffer, sizeof(buffer), + "Should be empty (source file full path): [%s]", cstr); info->CAPI->DisplaySatus(mf, buffer); info->CAPI->DefineSourceFileProperty(mf, "SOME_PROPERTY", "unused old prop", "This property is no longer used", 0); @@ -106,7 +108,8 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[]) "This property is for testing.", 0); info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE"); cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT"); - sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr); + snprintf(buffer, sizeof(buffer), + "Should be 0 (source file abstract property): [%p]", cstr); info->CAPI->DisplaySatus(mf, buffer); info->CAPI->DestroySourceFile(source_file); diff --git a/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c b/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c index af7b092..7176ebe 100644 --- a/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c +++ b/Tests/LoadCommandOneConfig/CMakeCommands/cmTestCommand.c @@ -75,10 +75,10 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[]) info->CAPI->DisplaySatus(mf, info->CAPI->GetStartOutputDirectory(mf)); info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentDirectory(mf)); info->CAPI->DisplaySatus(mf, info->CAPI->GetCurrentOutputDirectory(mf)); - sprintf(buffer, "Cache version: %d.%d, CMake version: %d.%d", - info->CAPI->GetCacheMajorVersion(mf), - info->CAPI->GetCacheMinorVersion(mf), - info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf)); + snprintf( + buffer, sizeof(buffer), "Cache version: %d.%d, CMake version: %d.%d", + info->CAPI->GetCacheMajorVersion(mf), info->CAPI->GetCacheMinorVersion(mf), + info->CAPI->GetMajorVersion(mf), info->CAPI->GetMinorVersion(mf)); info->CAPI->DisplaySatus(mf, buffer); if (info->CAPI->CommandExists(mf, "SET")) { info->CAPI->DisplaySatus(mf, "Command SET exists"); @@ -91,10 +91,12 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[]) source_file = info->CAPI->CreateNewSourceFile(mf); cstr = info->CAPI->SourceFileGetSourceName(source_file); - sprintf(buffer, "Should be empty (source file name): [%s]", cstr); + snprintf(buffer, sizeof(buffer), "Should be empty (source file name): [%s]", + cstr); info->CAPI->DisplaySatus(mf, buffer); cstr = info->CAPI->SourceFileGetFullPath(source_file); - sprintf(buffer, "Should be empty (source file full path): [%s]", cstr); + snprintf(buffer, sizeof(buffer), + "Should be empty (source file full path): [%s]", cstr); info->CAPI->DisplaySatus(mf, buffer); info->CAPI->DefineSourceFileProperty(mf, "SOME_PROPERTY", "unused old prop", "This property is no longer used", 0); @@ -106,7 +108,8 @@ static int CCONV InitialPass(void* inf, void* mf, int argc, char* argv[]) "This property is for testing.", 0); info->CAPI->SourceFileSetProperty(source_file, "SOME_PROPERTY2", "HERE"); cstr = info->CAPI->SourceFileGetProperty(source_file, "ABSTRACT"); - sprintf(buffer, "Should be 0 (source file abstract property): [%p]", cstr); + snprintf(buffer, sizeof(buffer), + "Should be 0 (source file abstract property): [%p]", cstr); info->CAPI->DisplaySatus(mf, buffer); info->CAPI->DestroySourceFile(source_file); diff --git a/Tests/MSVCDebugInformationFormat/CMakeLists.txt b/Tests/MSVCDebugInformationFormat/CMakeLists.txt new file mode 100644 index 0000000..b09bc6c --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/CMakeLists.txt @@ -0,0 +1,81 @@ +cmake_minimum_required(VERSION 3.24) +cmake_policy(SET CMP0141 NEW) + +# The debug information format flags do not change preprocessor definitions, +# so override our table of flags to artificially add a definition we can check. +set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/override-C.cmake) +set(CMAKE_USER_MAKE_RULES_OVERRIDE_CXX ${CMAKE_CURRENT_SOURCE_DIR}/override-CXX.cmake) +set(CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA ${CMAKE_CURRENT_SOURCE_DIR}/override-CUDA.cmake) +set(CMAKE_USER_MAKE_RULES_OVERRIDE_Fortran ${CMAKE_CURRENT_SOURCE_DIR}/override-Fortran.cmake) + +project(MSVCDebugInformationFormat) +if(CMake_TEST_CUDA) + enable_language(CUDA) +endif() +if(CMake_TEST_Fortran) + enable_language(Fortran) +endif() + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +if("${CMAKE_C_COMPILER_ID};${CMAKE_C_SIMULATE_ID};${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "Clang;MSVC;GNU") + set(verify_default VERIFY_Z7) + set(NO_COMPILER_PDB 1) +elseif("${CMAKE_C_COMPILER_ID};${CMAKE_C_SIMULATE_ID};${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "Clang;MSVC;MSVC") + set(verify_default VERIFY_Zi) + set(NO_EDIT_AND_CONTINUE 1) +else() + set(verify_default VERIFY_Zi) +endif() + +set(verify_def_Embedded -DVERIFY_Z7) +set(verify_def_ProgramDatabase -DVERIFY_Zi) +set(verify_def_EditAndContinue -DVERIFY_ZI) + +function(verify_combination format lang src) + # Test that try_compile builds with this debug format. + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "${format}") + set(CMAKE_TRY_COMPILE_CONFIGURATION "Debug") + set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + try_compile(${format}_COMPILES + ${CMAKE_CURRENT_BINARY_DIR}/try_compile/${format} + ${CMAKE_CURRENT_SOURCE_DIR}/${src} + COMPILE_DEFINITIONS ${verify_def_${format}} + CMAKE_FLAGS -DINCLUDE_DIRECTORIES=${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE ${format}_OUTPUT + ) + if(${format}_COMPILES) + message(STATUS "try_compile ${lang} with ${format} worked") + else() + string(REPLACE "\n" "\n " ${format}_OUTPUT " ${${format}_OUTPUT}") + message(SEND_ERROR "try_compile ${lang} with ${format} failed:\n${${format}_OUTPUT}") + endif() + + # Test that targets build with this debug format. + set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<$<BOOL:$<TARGET_PROPERTY:BOOL_TRUE>>:${format}>$<$<BOOL:$<TARGET_PROPERTY:BOOL_FALSE>>:BadContent>") + add_library(${format}-${lang} ${src}) + set_property(TARGET ${format}-${lang} PROPERTY BOOL_TRUE TRUE) + target_compile_definitions(${format}-${lang} PRIVATE ${verify_def_${format}}) +endfunction() + +function(verify lang src) + add_library(default-${lang} ${src}) + target_compile_definitions(default-${lang} PRIVATE "$<$<CONFIG:Debug,RelWithDebInfo>:${verify_default}>") + + verify_combination(Embedded ${lang} ${src}) + if(NOT NO_COMPILER_PDB) + verify_combination(ProgramDatabase ${lang} ${src}) + if(NOT NO_EDIT_AND_CONTINUE AND NOT lang MATCHES "^(Fortran)$") + verify_combination(EditAndContinue ${lang} ${src}) + endif() + endif() +endfunction() + +verify(C verify.c) +verify(CXX verify.cxx) +if(CMake_TEST_CUDA) + verify(CUDA verify.cu) +endif() +if(CMake_TEST_Fortran) + verify(Fortran verify.F90) +endif() diff --git a/Tests/MSVCDebugInformationFormat/override-C.cmake b/Tests/MSVCDebugInformationFormat/override-C.cmake new file mode 100644 index 0000000..e8f5ae4 --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/override-C.cmake @@ -0,0 +1,7 @@ +set(var "CMAKE_C_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded") +string(REPLACE "-Z7" "-Z7;-DTEST_Z7" "${var}" "${${var}}") +string(REPLACE "-gcodeview" "-gcodeview;-DTEST_Z7" "${var}" "${${var}}") +set(var "CMAKE_C_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase") +string(REPLACE "-Zi" "-Zi;-DTEST_Zi" "${var}" "${${var}}") +set(var "CMAKE_C_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue") +string(REPLACE "-ZI" "-ZI;-DTEST_ZI" "${var}" "${${var}}") diff --git a/Tests/MSVCDebugInformationFormat/override-CUDA.cmake b/Tests/MSVCDebugInformationFormat/override-CUDA.cmake new file mode 100644 index 0000000..f870775 --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/override-CUDA.cmake @@ -0,0 +1,6 @@ +set(var "CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded") +string(REPLACE "-Z7" "-Z7;-DTEST_Z7" "${var}" "${${var}}") +set(var "CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase") +string(REPLACE "-Zi" "-Zi;-DTEST_Zi" "${var}" "${${var}}") +set(var "CMAKE_CUDA_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue") +string(REPLACE "-ZI" "-ZI;-DTEST_ZI" "${var}" "${${var}}") diff --git a/Tests/MSVCDebugInformationFormat/override-CXX.cmake b/Tests/MSVCDebugInformationFormat/override-CXX.cmake new file mode 100644 index 0000000..caa23fe --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/override-CXX.cmake @@ -0,0 +1,7 @@ +set(var "CMAKE_CXX_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded") +string(REPLACE "-Z7" "-Z7;-DTEST_Z7" "${var}" "${${var}}") +string(REPLACE "-gcodeview" "-gcodeview;-DTEST_Z7" "${var}" "${${var}}") +set(var "CMAKE_CXX_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase") +string(REPLACE "-Zi" "-Zi;-DTEST_Zi" "${var}" "${${var}}") +set(var "CMAKE_CXX_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_EditAndContinue") +string(REPLACE "-ZI" "-ZI;-DTEST_ZI" "${var}" "${${var}}") diff --git a/Tests/MSVCDebugInformationFormat/override-Fortran.cmake b/Tests/MSVCDebugInformationFormat/override-Fortran.cmake new file mode 100644 index 0000000..5d2db58 --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/override-Fortran.cmake @@ -0,0 +1,4 @@ +set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_Embedded") +string(REPLACE "-Z7" "-Z7;-DTEST_Z7" "${var}" "${${var}}") +set(var "CMAKE_Fortran_COMPILE_OPTIONS_MSVC_DEBUG_INFORMATION_FORMAT_ProgramDatabase") +string(REPLACE "-Zi" "-Zi;-DTEST_Zi" "${var}" "${${var}}") diff --git a/Tests/MSVCDebugInformationFormat/verify.F90 b/Tests/MSVCDebugInformationFormat/verify.F90 new file mode 100644 index 0000000..741bca6 --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/verify.F90 @@ -0,0 +1 @@ +#include "verify.h" diff --git a/Tests/MSVCDebugInformationFormat/verify.c b/Tests/MSVCDebugInformationFormat/verify.c new file mode 100644 index 0000000..741bca6 --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/verify.c @@ -0,0 +1 @@ +#include "verify.h" diff --git a/Tests/MSVCDebugInformationFormat/verify.cu b/Tests/MSVCDebugInformationFormat/verify.cu new file mode 100644 index 0000000..741bca6 --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/verify.cu @@ -0,0 +1 @@ +#include "verify.h" diff --git a/Tests/MSVCDebugInformationFormat/verify.cxx b/Tests/MSVCDebugInformationFormat/verify.cxx new file mode 100644 index 0000000..741bca6 --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/verify.cxx @@ -0,0 +1 @@ +#include "verify.h" diff --git a/Tests/MSVCDebugInformationFormat/verify.h b/Tests/MSVCDebugInformationFormat/verify.h new file mode 100644 index 0000000..4bd6529 --- /dev/null +++ b/Tests/MSVCDebugInformationFormat/verify.h @@ -0,0 +1,29 @@ +#ifdef VERIFY_Z7 +# ifndef TEST_Z7 +# error "TEST_Z7 incorrectly not defined by debug format selection" +# endif +#else +# ifdef TEST_Z7 +# error "TEST_Z7 incorrectly defined by non-debug format selection" +# endif +#endif + +#ifdef VERIFY_Zi +# ifndef TEST_Zi +# error "TEST_Zi incorrectly not defined by debug format selection" +# endif +#else +# ifdef TEST_Zi +# error "TEST_Zi incorrectly defined by non-debug format selection" +# endif +#endif + +#ifdef VERIFY_ZI +# ifndef TEST_ZI +# error "TEST_ZI incorrectly not defined by debug format selection" +# endif +#else +# ifdef TEST_ZI +# error "TEST_ZI incorrectly defined by non-debug format selection" +# endif +#endif diff --git a/Tests/Module/CheckIPOSupported-CUDA/CMakeLists.txt b/Tests/Module/CheckIPOSupported-CUDA/CMakeLists.txt new file mode 100644 index 0000000..9dd670e --- /dev/null +++ b/Tests/Module/CheckIPOSupported-CUDA/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.8) +project(CheckIPOSupported-CUDA LANGUAGES CUDA) + +cmake_policy(SET CMP0069 NEW) + +include(CheckIPOSupported) +check_ipo_supported(RESULT ipo_supported OUTPUT ipo_output) +if(ipo_supported) + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) +endif() + +if(NOT ipo_supported AND CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA" + AND CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.2) + message(FATAL_ERROR "CheckIPOSupported failed to correctly identify NVIDIA CUDA IPO support") +endif() + +set(CMAKE_CUDA_SEPARABLE_COMPILATION ON) + +add_library(foo STATIC foo.cu) +set_target_properties(foo PROPERTIES + WINDOWS_EXPORT_ALL_SYMBOLS ON + POSITION_INDEPENDENT_CODE ON) + +add_library(bar SHARED bar.cu) +set_target_properties(bar PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON) +target_link_libraries(bar PRIVATE foo) + +add_executable(CheckIPOSupported-CUDA main.cu) +target_link_libraries(CheckIPOSupported-CUDA PUBLIC bar) + +enable_testing() +add_test(NAME CheckIPOSupported-CUDA COMMAND CheckIPOSupported-CUDA) diff --git a/Tests/Module/CheckIPOSupported-CUDA/bar.cu b/Tests/Module/CheckIPOSupported-CUDA/bar.cu new file mode 100644 index 0000000..79b276d --- /dev/null +++ b/Tests/Module/CheckIPOSupported-CUDA/bar.cu @@ -0,0 +1,12 @@ +__device__ int foo_func(int); + +void __global__ bar_kernel(int x) +{ + foo_func(x); +} + +int launch_kernel(int x) +{ + bar_kernel<<<1, 1>>>(x); + return x; +} diff --git a/Tests/Module/CheckIPOSupported-CUDA/foo.cu b/Tests/Module/CheckIPOSupported-CUDA/foo.cu new file mode 100644 index 0000000..416607b --- /dev/null +++ b/Tests/Module/CheckIPOSupported-CUDA/foo.cu @@ -0,0 +1,4 @@ +extern __device__ int foo_func(int a) +{ + return a * 42 + 9; +} diff --git a/Tests/Module/CheckIPOSupported-CUDA/main.cu b/Tests/Module/CheckIPOSupported-CUDA/main.cu new file mode 100644 index 0000000..8ef4873 --- /dev/null +++ b/Tests/Module/CheckIPOSupported-CUDA/main.cu @@ -0,0 +1,62 @@ +#include <iostream> + +#include "cuda.h" + +#ifdef _WIN32 +# define IMPORT __declspec(dllimport) +#else +# define IMPORT +#endif + +IMPORT int launch_kernel(int x); + +int choose_cuda_device() +{ + int nDevices = 0; + cudaError_t err = cudaGetDeviceCount(&nDevices); + if (err != cudaSuccess) { + std::cerr << "Failed to retrieve the number of CUDA enabled devices" + << std::endl; + return 1; + } + for (int i = 0; i < nDevices; ++i) { + cudaDeviceProp prop; + cudaError_t err = cudaGetDeviceProperties(&prop, i); + if (err != cudaSuccess) { + std::cerr << "Could not retrieve properties from CUDA device " << i + << std::endl; + return 1; + } + std::cout << "prop.major: " << prop.major << std::endl; + err = cudaSetDevice(i); + if (err != cudaSuccess) { + std::cout << "Could not select CUDA device " << i << std::endl; + } else { + return 0; + } + } + + std::cout << "Could not find a CUDA enabled card" << std::endl; + + return 1; +} + +int main() +{ + int ret = choose_cuda_device(); + if (ret) { + return 0; + } + + cudaError_t err; + launch_kernel(1); + err = cudaGetLastError(); + if (err != cudaSuccess) { + std::cerr << "launch_kernel: kernel launch should have passed.\n " + "Error message: " + << cudaGetErrorString(err) << std::endl; + return 1; + } + + return 0; +} diff --git a/Tests/ModuleDefinition/CMakeLists.txt b/Tests/ModuleDefinition/CMakeLists.txt index 567fb4b..483bd8b 100644 --- a/Tests/ModuleDefinition/CMakeLists.txt +++ b/Tests/ModuleDefinition/CMakeLists.txt @@ -15,7 +15,17 @@ add_custom_command(OUTPUT example_dll_gen.def add_library(example_dll_gen SHARED example_dll_gen.c example_dll_gen.def) # Test /DEF:<file> flag recognition for VS. -if(MSVC OR CMAKE_C_COMPILER_ID STREQUAL "Intel") +if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM") + # IntelLLVM for MSVC frontend variant needs the /DEF flag wrapped to be sent + # to the linker, which happens automatically when the DEF file is added + # to the sources. + add_library(example_dll_2 SHARED + example_dll_2.c + "${ModuleDefinition_SOURCE_DIR}/example_dll_2.def" + ) + set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS EXAMPLE_DLL_2) + set(example_dll_2 example_dll_2) +elseif(MSVC OR CMAKE_C_COMPILER_ID STREQUAL "Intel") add_library(example_dll_2 SHARED example_dll_2.c) set_property(TARGET example_dll_2 PROPERTY LINK_FLAGS /DEF:"${ModuleDefinition_SOURCE_DIR}/example_dll_2.def") diff --git a/Tests/Preprocess/CMakeLists.txt b/Tests/Preprocess/CMakeLists.txt index 4347459..84ca5e8 100644 --- a/Tests/Preprocess/CMakeLists.txt +++ b/Tests/Preprocess/CMakeLists.txt @@ -197,9 +197,14 @@ endif() #----------------------------------------------------------------------------- # Inform the test if the debug configuration is getting built. -# The NDEBUG definition takes care of this for release. string(APPEND CMAKE_C_FLAGS_DEBUG " -DPREPROCESS_DEBUG") string(APPEND CMAKE_CXX_FLAGS_DEBUG " -DPREPROCESS_DEBUG") +string(APPEND CMAKE_C_FLAGS_RELEASE " -DPREPROCESS_NDEBUG") +string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DPREPROCESS_NDEBUG") +string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -DPREPROCESS_NDEBUG") +string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DPREPROCESS_NDEBUG") +string(APPEND CMAKE_C_FLAGS_MINSIZEREL " -DPREPROCESS_NDEBUG") +string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DPREPROCESS_NDEBUG") # Inform the test if it built from Xcode. if(PP_XCODE) diff --git a/Tests/Preprocess/preprocess.c b/Tests/Preprocess/preprocess.c index b3117da..88f9e97 100644 --- a/Tests/Preprocess/preprocess.c +++ b/Tests/Preprocess/preprocess.c @@ -33,7 +33,7 @@ int check_defines_C(void) result = 0; } } -#ifdef NDEBUG +#ifdef PREPROCESS_NDEBUG # ifdef FILE_DEF_DEBUG { fprintf(stderr, "FILE_DEF_DEBUG should not be defined in C\n"); diff --git a/Tests/Preprocess/preprocess.cxx b/Tests/Preprocess/preprocess.cxx index f2fffef..50150d1 100644 --- a/Tests/Preprocess/preprocess.cxx +++ b/Tests/Preprocess/preprocess.cxx @@ -35,7 +35,7 @@ int check_defines_CXX() result = 0; } } -#ifdef NDEBUG +#ifdef PREPROCESS_NDEBUG # ifdef FILE_DEF_DEBUG { fprintf(stderr, "FILE_DEF_DEBUG should not be defined in CXX\n"); diff --git a/Tests/RunCMake/AutoExportDll/AutoExport.cmake b/Tests/RunCMake/AutoExportDll/AutoExport.cmake index dbcf4b8..fe57d56 100644 --- a/Tests/RunCMake/AutoExportDll/AutoExport.cmake +++ b/Tests/RunCMake/AutoExportDll/AutoExport.cmake @@ -7,7 +7,7 @@ set_property(TARGET objlib PROPERTY POSITION_INDEPENDENT_CODE 1) add_library(autoexport SHARED hello.cxx world.cxx foo.c $<TARGET_OBJECTS:objlib>) add_library(autoexport3 SHARED cppCLI.cxx) if(MSVC AND NOT MSVC_VERSION VERSION_LESS 1600 - AND NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") + AND NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64") set_property(TARGET autoexport3 PROPERTY COMMON_LANGUAGE_RUNTIME "") endif() @@ -17,7 +17,7 @@ if(MSVC) add_library(autoexport_for_exec SHARED hello2.c) target_link_libraries(autoexport_for_exec say) if(NOT MSVC_VERSION VERSION_LESS 1600 AND - NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") + NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64") enable_language(ASM_MASM) target_sources(autoexport PRIVATE nop.asm) set_property(SOURCE nop.asm PROPERTY COMPILE_FLAGS /safeseh) diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 06f416b..8099079 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -60,8 +60,7 @@ set(run_BuildDepends_skip_step_3 1) run_BuildDepends(C-Exe) if(NOT RunCMake_GENERATOR STREQUAL "Xcode") - if(RunCMake_GENERATOR MATCHES "Visual Studio 10" OR - RunCMake_GENERATOR_TOOLSET MATCHES "^(v80|v90|v100)$") + if(RunCMake_GENERATOR_TOOLSET MATCHES "^(v80|v90|v100)$") # VS 10 forgets to re-link when a manifest changes set(run_BuildDepends_skip_step_2 1) endif() diff --git a/Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt b/Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt new file mode 100644 index 0000000..5d09fcf --- /dev/null +++ b/Tests/RunCMake/CMP0102/CMP0102-OLD-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0102-OLD.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0102 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake index 61e046f..074db65 100644 --- a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake @@ -4,3 +4,4 @@ run_cmake_script(Regex-CMP0127-NEW) run_cmake_script(Regex-CMP0127-OLD) run_cmake_script(Parentheses-CMP0127-NEW) run_cmake_script(Parentheses-CMP0127-WARN) +run_cmake_script(UseDotSymbol) diff --git a/Tests/RunCMake/CMakeDependentOption/UseDotSymbol-stdout.txt b/Tests/RunCMake/CMakeDependentOption/UseDotSymbol-stdout.txt new file mode 100644 index 0000000..15b56a1 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/UseDotSymbol-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/UseDotSymbol.cmake b/Tests/RunCMake/CMakeDependentOption/UseDotSymbol.cmake new file mode 100644 index 0000000..8f07c48 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/UseDotSymbol.cmake @@ -0,0 +1,4 @@ +include(CMakeDependentOption) + +cmake_dependent_option(USE_FOO "Use Foo" ON "CMAKE_VERSION VERSION_GREATER_EQUAL 3.08" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 09f248e..6c5ab7f 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -295,6 +295,19 @@ if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja") add_RunCMake_test(CompilerChange) endif() add_RunCMake_test(CompilerNotFound) +if (APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang|GNU") + list(APPEND CompilerTest_ARGS -DCMake_TEST_OBJC=1) +endif() +if(CMAKE_Fortran_COMPILER) + list(APPEND CompilerTest_ARGS -DCMake_TEST_Fortran=1) +endif() +foreach(lang IN ITEMS CUDA HIP ISPC) + if(CMake_TEST_${lang}) + list(APPEND CompilerTest_ARGS -DCMake_TEST_${lang}=1) + endif() +endforeach() +add_RunCMake_test(CompilerTest) +set_property(TEST RunCMake.CompilerTest APPEND PROPERTY LABELS "CUDA" "HIP" "ISPC") add_RunCMake_test(Configure -DMSVC_IDE=${MSVC_IDE}) add_RunCMake_test(DisallowedCommands) if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja") @@ -305,6 +318,9 @@ add_RunCMake_test(ExportImport) add_RunCMake_test(ExternalData) add_RunCMake_test(FeatureSummary) add_RunCMake_test(FPHSA) +if(CMAKE_USE_SYSTEM_JSONCPP) + list(APPEND FileAPI_ARGS -DJsonCpp_VERSION_STRING=${JsonCpp_VERSION_STRING}) +endif() add_RunCMake_test(FileAPI -DPython_EXECUTABLE=${Python_EXECUTABLE} -DCMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}) add_RunCMake_test(FindBoost) @@ -356,6 +372,7 @@ if(MSVC) add_RunCMake_test(MSVCRuntimeLibrary) add_RunCMake_test(MSVCRuntimeTypeInfo) add_RunCMake_test(MSVCWarningFlags) + add_RunCMake_test(MSVCDebugInformationFormat) endif() if(XCODE_VERSION) set(ObjectLibrary_ARGS -DXCODE_VERSION=${XCODE_VERSION}) @@ -453,6 +470,7 @@ add_RunCMake_test(find_path) add_RunCMake_test(find_program -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}) add_RunCMake_test(foreach) add_RunCMake_test(function) +add_RunCMake_test(block) add_RunCMake_test(get_filename_component) add_RunCMake_test(get_property) add_RunCMake_test(if) @@ -522,7 +540,9 @@ function(add_RunCMake_test_try_compile) set(CMAKE_CXX_STANDARD_DEFAULT 14) endif() endif() - foreach(var + foreach( + var + IN ITEMS CMAKE_SYSTEM_NAME CMAKE_C_COMPILER_ID CMAKE_C_COMPILER_VERSION @@ -536,7 +556,7 @@ function(add_RunCMake_test_try_compile) CMake_TEST_FILESYSTEM_1S CMAKE_OBJC_STANDARD_DEFAULT CMAKE_OBJCXX_STANDARD_DEFAULT - ) + ) if(DEFINED ${var}) list(APPEND try_compile_ARGS -D${var}=${${var}}) endif() @@ -566,6 +586,9 @@ if(CMake_TEST_CUDA) endif() add_RunCMake_test(DependencyGraph -DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER}) +# Add C++ Module tests. +add_RunCMake_test(CXXModules -DCMake_TEST_MODULE_COMPILATION=${CMake_TEST_MODULE_COMPILATION} -DCMake_TEST_MODULE_COMPILATION_RULES=${CMake_TEST_MODULE_COMPILATION_RULES}) + # ctresalloc links against CMakeLib and CTestLib, which means it can't be built # if CMake_TEST_EXTERNAL_CMAKE is activated (the compiler might be different.) # So, it has to be provided in the original build tree. @@ -689,6 +712,8 @@ add_RunCMake_test(target_link_libraries-LINK_LIBRARY -DCMAKE_SYSTEM_NAME=${CMAKE -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} -DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION} -DMSVC_VERSION=${MSVC_VERSION} + -DXCODE=${XCODE} + -DXCODE_VERSION=${XCODE_VERSION} -DCMAKE_SHARED_LIBRARY_PREFIX=${CMAKE_SHARED_LIBRARY_PREFIX} -DCMAKE_SHARED_LIBRARY_SUFFIX=${CMAKE_SHARED_LIBRARY_SUFFIX} -DCMAKE_IMPORT_LIBRARY_PREFIX=${CMAKE_IMPORT_LIBRARY_PREFIX} @@ -948,7 +973,7 @@ if(CMake_TEST_ANDROID_NDK OR CMake_TEST_ANDROID_STANDALONE_TOOLCHAIN) if(NOT "${CMAKE_GENERATOR}" MATCHES "Make|Ninja|Visual Studio 1[456]") message(FATAL_ERROR "Android tests supported only by Makefile, Ninja, and Visual Studio >= 14 generators") endif() - foreach(v TEST_ANDROID_NDK TEST_ANDROID_STANDALONE_TOOLCHAIN) + foreach(v IN ITEMS TEST_ANDROID_NDK TEST_ANDROID_STANDALONE_TOOLCHAIN) if(CMake_${v}) string(REPLACE ";" "|" ${v} "${CMake_${v}}") list(APPEND Android_ARGS "-D${v}=${${v}}") @@ -967,7 +992,7 @@ endif() if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^9]|9[0-9])") add_RunCMake_test(CSharpCustomCommand) - if(NOT CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64") + if(NOT CMAKE_VS_PLATFORM_NAME STREQUAL "ARM64") add_RunCMake_test(CSharpReferenceImport) endif() endif() @@ -992,6 +1017,14 @@ add_RunCMake_test(CMakePresetsTest -DPython_EXECUTABLE=${Python_EXECUTABLE} -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA} ) +add_RunCMake_test(CMakePresetsPackage + -DPython_EXECUTABLE=${Python_EXECUTABLE} + -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA} + ) +add_RunCMake_test(CMakePresetsWorkflow + -DPython_EXECUTABLE=${Python_EXECUTABLE} + -DCMake_TEST_JSON_SCHEMA=${CMake_TEST_JSON_SCHEMA} + ) add_RunCMake_test(VerifyHeaderSets) diff --git a/Tests/RunCMake/CMakePresets/Comment-stderr.txt b/Tests/RunCMake/CMakePresets/Comment-stderr.txt index 2f404bc..b3b6b66 100644 --- a/Tests/RunCMake/CMakePresets/Comment-stderr.txt +++ b/Tests/RunCMake/CMakePresets/Comment-stderr.txt @@ -1,2 +1,9 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/Comment: JSON parse error$ +]*/Tests/RunCMake/CMakePresets/Comment: JSON parse error +Errors: +[^ +]*Comment\/CMakePresets.json: +\* Line 1, Column 1 + Syntax error: value, object or array expected\. +\* Line 2, Column 1 + Extra non-whitespace after JSON value\.$ diff --git a/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt b/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt new file mode 100644 index 0000000..57b714d --- /dev/null +++ b/Tests/RunCMake/CMakePresets/DocumentationExampleListAllPresets-stdout.txt @@ -0,0 +1,22 @@ +^Not searching for unused variables given on the command line\. +Available configure presets: + + "default" ?- Default Config + "ninja-multi" ?- Ninja Multi-Config( + "windows-only" - Windows-only configuration)? + +Available build presets: + + "default" + +Available test presets: + + "default" + +Available package presets: + + "default" + +Available workflow presets: + + "default"$ diff --git a/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt index 6970674..0d3c500 100644 --- a/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt +++ b/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt @@ -1,2 +1,5 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/EmptyPresetName: Invalid preset$ +]*/Tests/RunCMake/CMakePresets/EmptyPresetName: Invalid preset +Errors: +[^ +]*/EmptyPresetName/CMakePresets.json$ diff --git a/Tests/RunCMake/CMakePresets/GoodNoSCache.cmake b/Tests/RunCMake/CMakePresets/GoodNoSCache.cmake index df58e72..d9e399f 100644 --- a/Tests/RunCMake/CMakePresets/GoodNoSCache.cmake +++ b/Tests/RunCMake/CMakePresets/GoodNoSCache.cmake @@ -1,4 +1,5 @@ include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake) get_filename_component(_parent "${CMAKE_SOURCE_DIR}" DIRECTORY) +file(REAL_PATH "${_parent}" _parent) test_variable(CMAKE_BINARY_DIR "" "${_parent}/GoodNoSCachePrep-build") diff --git a/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt b/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt index 7ccabab..85a2d78 100644 --- a/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt +++ b/Tests/RunCMake/CMakePresets/IncludeNotFound-stderr.txt @@ -1,2 +1,5 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/IncludeNotFound: File not found$ +]*/Tests/RunCMake/CMakePresets/IncludeNotFound: File not found +Errors: +[^ +]*/IncludeNotFound/NotFound.json: Failed to read file$ diff --git a/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt b/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt index a43bf77..89eff9f 100644 --- a/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt +++ b/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt @@ -1,2 +1,9 @@ ^CMake Error: Could not read presets from [^ -]*/Tests/RunCMake/CMakePresets/JSONParseError: JSON parse error$ +]*/Tests/RunCMake/CMakePresets/JSONParseError: JSON parse error +Errors: +[^ +]*JSONParseError/CMakePresets.json: +\* Line 1, Column 1 + Syntax error: value, object or array expected\. +\* Line 1, Column 1 + A valid JSON document must be either an array or an object value\.$ diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt new file mode 100644 index 0000000..38f52aa --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild-stdout.txt @@ -0,0 +1,8 @@ +^Not searching for unused variables given on the command line. +Available configure presets: + + "default" + +Available test presets: + + "default"$ diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild.json.in b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild.json.in new file mode 100644 index 0000000..9259477 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoBuild.json.in @@ -0,0 +1,14 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default" + } + ], + "testPresets": [ + { + "name": "default", + "configurePreset": "default" + } + ] +} diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt new file mode 100644 index 0000000..8cac0a8 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest-stdout.txt @@ -0,0 +1,8 @@ +^Not searching for unused variables given on the command line. +Available configure presets: + + "default" + +Available build presets: + + "default"$ diff --git a/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest.json.in b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest.json.in new file mode 100644 index 0000000..33fd036 --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ListAllPresetsNoTest.json.in @@ -0,0 +1,14 @@ +{ + "version": 3, + "configurePresets": [ + { + "name": "default" + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default" + } + ] +} diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-result.txt b/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-result.txt +++ b/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-result.txt diff --git a/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-stderr.txt b/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-stderr.txt new file mode 100644 index 0000000..153abee --- /dev/null +++ b/Tests/RunCMake/CMakePresets/ListPresetsInvalidType-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error: Invalid value specified for --list-presets\. +Valid values are configure, build, test, package, or all\. When no value is passed the default is configure\. +CMake Error: Run 'cmake --help' for all supported options\.$ diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake index d097086..efa838e 100644 --- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake @@ -289,6 +289,7 @@ run_cmake_presets(UserInheritance) # Test listing presets set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/ListPresets.json.in") run_cmake_presets(ListPresets --list-presets) +run_cmake_presets(ListPresetsInvalidType --list-presets=invalid-type) set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/ListPresetsWorkingDir") set(RunCMake_TEST_NO_CLEAN 1) @@ -304,6 +305,12 @@ unset(RunCMake_TEST_BINARY_DIR) run_cmake_presets(ListPresetsNoSuchPreset) run_cmake_presets(ListPresetsHidden) +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/ListAllPresetsNoBuild.json.in") +run_cmake_presets(ListAllPresetsNoBuild --list-presets=all) + +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/ListAllPresetsNoTest.json.in") +run_cmake_presets(ListAllPresetsNoTest --list-presets=all) + # Test warning and error flags set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Warnings.json.in") set(CMakePresets_WARN_UNUSED_CLI 1) @@ -401,4 +408,5 @@ set(CMakePresets_EXTRA_FILES "${RunCMake_SOURCE_DIR}/moreThings.json.in" ) run_cmake_presets(DocumentationExample --preset=default) +run_cmake_presets(DocumentationExampleListAllPresets --list-presets=all) unset(CMakePresets_EXTRA_FILES) diff --git a/Tests/RunCMake/CMakePresetsPackage/CMakeLists.txt.in b/Tests/RunCMake/CMakePresetsPackage/CMakeLists.txt.in new file mode 100644 index 0000000..129184a --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/CMakeLists.txt.in @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.19) +project("@CASE_NAME@" NONE) +include("@CASE_SOURCE_DIR@/@CASE_NAME@.cmake") diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-config-file-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-config-file-check.cmake new file mode 100644 index 0000000..40240f9 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-config-file-check.cmake @@ -0,0 +1,6 @@ +include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake") + +set(filename "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages/${CPACK_TOPLEVEL_TAG}/TGZ/config-file-alt.tar.gz") +if(NOT EXISTS "${filename}") + set(RunCMake_TEST_FAILED "Expected ${filename} to exist but it does not") +endif() diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-configurations-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-configurations-check.cmake new file mode 100644 index 0000000..3d684af --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-configurations-check.cmake @@ -0,0 +1,18 @@ +if(RunCMake_GENERATOR_IS_MULTI_CONFIG) + include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake") + set(cpack_dir "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages/${CPACK_TOPLEVEL_TAG}") + set(contents [[Debug +Release +]]) + + file(GLOB dirs RELATIVE "${cpack_dir}" "${cpack_dir}/*") + foreach(dir IN LISTS dirs) + set(configs_file "${cpack_dir}/${dir}/${CPACK_PACKAGE_FILE_NAME}/configs.txt") + file(READ "${configs_file}" actual_contents) + if(NOT contents STREQUAL actual_contents) + string(REPLACE "\n" "\n " contents_formatted "${contents}") + string(REPLACE "\n" "\n " actual_contents_formatted "${actual_contents}") + string(APPEND RunCMake_TEST_FAILED "Expected contents of ${configs_file}:\n ${contents_formatted}\nActual contents:\n ${actual_contents_formatted}\n") + endif() + endforeach() +endif() diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-debug-stdout.txt b/Tests/RunCMake/CMakePresetsPackage/Good-package-debug-stdout.txt new file mode 100644 index 0000000..be885b4 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-debug-stdout.txt @@ -0,0 +1,2 @@ +CPack: [^ +]* Enable Debug diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-generators-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-generators-check.cmake new file mode 100644 index 0000000..aaa75e4 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-generators-check.cmake @@ -0,0 +1 @@ +check_cpack_packages("TBZ2;TXZ" "") diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-no-environment-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-no-environment-check.cmake new file mode 100644 index 0000000..205e7b7 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-no-environment-check.cmake @@ -0,0 +1,7 @@ +check_cpack_packages("TGZ;TXZ" [[TEST_ENV not defined +TEST_ENV_REF=xx +TEST_ENV_OVERRIDE not defined +TEST_ENV_OVERRIDE_REF not defined +]]) + +include("${RunCMake_SOURCE_DIR}/check.cmake") diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-package-directory-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-directory-check.cmake new file mode 100644 index 0000000..8f4b771 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-directory-check.cmake @@ -0,0 +1,6 @@ +include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake") + +set(filename "${RunCMake_TEST_BINARY_DIR}/default/package-directory/_CPack_Packages/${CPACK_TOPLEVEL_TAG}/TGZ/${CPACK_PACKAGE_FILE_NAME}.tar.gz") +if(NOT EXISTS "${filename}") + set(RunCMake_TEST_FAILED "Expected ${filename} to exist but it does not") +endif() diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-package-name-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-name-check.cmake new file mode 100644 index 0000000..fdc4824 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-name-check.cmake @@ -0,0 +1,7 @@ +include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake") + +file(READ "${RunCMake_TEST_BINARY_DIR}/default/${CPACK_PACKAGE_FILE_NAME}.json" contents) +string(JSON package_name GET "${contents}" packageName) +if(NOT package_name STREQUAL "package-name") + set(RunCMake_TEST_FAILED "Expected package name to be \"package-name\" but it was \"${package_name}\"") +endif() diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-package-version-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-version-check.cmake new file mode 100644 index 0000000..dba9110 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-package-version-check.cmake @@ -0,0 +1,7 @@ +include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake") + +file(READ "${RunCMake_TEST_BINARY_DIR}/default/${CPACK_PACKAGE_FILE_NAME}.json" contents) +string(JSON package_version GET "${contents}" packageVersion) +if(NOT package_version STREQUAL "1.0") + set(RunCMake_TEST_FAILED "Expected package version to be \"1.0\" but it was \"${package_version}\"") +endif() diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-variables-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-variables-check.cmake new file mode 100644 index 0000000..2858170 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-variables-check.cmake @@ -0,0 +1,6 @@ +include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake") + +set(filename "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages/${CPACK_TOPLEVEL_TAG}/TGZ/variables-package.tar.gz") +if(NOT EXISTS "${filename}") + set(RunCMake_TEST_FAILED "Expected ${filename} to exist but it does not") +endif() diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-verbose-stdout.txt b/Tests/RunCMake/CMakePresetsPackage/Good-package-verbose-stdout.txt new file mode 100644 index 0000000..22fd115 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-verbose-stdout.txt @@ -0,0 +1 @@ +CPack: Enable Verbose diff --git a/Tests/RunCMake/CMakePresetsPackage/Good-package-with-environment-check.cmake b/Tests/RunCMake/CMakePresetsPackage/Good-package-with-environment-check.cmake new file mode 100644 index 0000000..a775e4d --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good-package-with-environment-check.cmake @@ -0,0 +1,7 @@ +check_cpack_packages("TGZ;TXZ" [[TEST_ENV=Environment variable +TEST_ENV_REF=xEnvironment variablex +TEST_ENV_OVERRIDE=Override +TEST_ENV_OVERRIDE_REF=xOverridex +]]) + +include("${RunCMake_SOURCE_DIR}/check.cmake") diff --git a/Tests/RunCMake/CMakePresetsPackage/Good.cmake b/Tests/RunCMake/CMakePresetsPackage/Good.cmake new file mode 100644 index 0000000..d019443 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good.cmake @@ -0,0 +1,31 @@ +set(CPACK_PACKAGE_NAME Good) +set(CPACK_GENERATOR "TGZ;TXZ") + +include(CPack) + +install(CODE [[ +function(print_env name) + if(DEFINED ENV{${name}}) + file(APPEND $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/env.txt "${name}=$ENV{${name}}\n") + else() + file(APPEND $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/env.txt "${name} not defined\n") + endif() +endfunction() + +file(REMOVE $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/env.txt) +print_env(TEST_ENV) +print_env(TEST_ENV_REF) +print_env(TEST_ENV_OVERRIDE) +print_env(TEST_ENV_OVERRIDE_REF) + +file(APPEND $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/configs.txt "$<CONFIG>\n") +]]) + +file(WRITE "${CMAKE_BINARY_DIR}/CPackConfigAlt.cmake" [[include(${CMAKE_CURRENT_LIST_DIR}/CPackConfig.cmake) +set(CPACK_PACKAGE_FILE_NAME "config-file-alt") +]]) + +file(WRITE "${CMAKE_BINARY_DIR}/external_package.cmake" [[if(NOT CPACK_PACKAGE_VENDOR STREQUAL "some-vendor") + message(FATAL_ERROR "Expected vendor to be \"some-vendor\" but it was \"${CPACK_PACKAGE_VENDOR}\"") +endif() +]]) diff --git a/Tests/RunCMake/CMakePresetsPackage/Good.json.in b/Tests/RunCMake/CMakePresetsPackage/Good.json.in new file mode 100644 index 0000000..0c0e7d9 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/Good.json.in @@ -0,0 +1,135 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "generator": "@RunCMake_GENERATOR@", + "binaryDir": "${sourceDir}/build/${presetName}", + "environment": { + "TEST_ENV": "Environment variable", + "TEST_ENV_OVERRIDE": "Overridden environment variable" + } + } + ], + "buildPresets": [ + { + "name": "build-default-debug", + "configurePreset": "default", + "configuration": "Debug" + }, + { + "name": "build-default-release", + "inherits": "build-default-debug", + "configuration": "Release" + } + ], + "packagePresets": [ + { + "name": "minimal", + "configurePreset": "default" + }, + { + "name": "defaults", + "hidden": false, + "inherits": [], + "vendor": {}, + "displayName": "", + "description": "", + "environment": {}, + "configurePreset": "default", + "inheritConfigureEnvironment": true + }, + { + "name": "no-environment", + "configurePreset": "default", + "inheritConfigureEnvironment": false, + "environment": { + "TEST_ENV_REF": "x$env{TEST_ENV}x" + } + }, + { + "name": "with-environment", + "inherits": "no-environment", + "inheritConfigureEnvironment": true, + "environment": { + "TEST_ENV_OVERRIDE": "Override", + "TEST_ENV_OVERRIDE_REF": "x$env{TEST_ENV_OVERRIDE}x", + "TEST_ENV_REF": "x$env{TEST_ENV}x" + } + }, + { + "name": "generators", + "inherits": "minimal", + "generators": [ + "TBZ2", + "TXZ" + ] + }, + { + "name": "configurations", + "inherits": "minimal", + "configurations": [ + "Debug", + "Release" + ] + }, + { + "name": "variables", + "inherits": "minimal", + "variables": { + "CPACK_PACKAGE_FILE_NAME": "variables-package" + } + }, + { + "name": "config-file", + "inherits": "minimal", + "configFile": "CPackConfigAlt.cmake" + }, + { + "name": "debug", + "inherits": "minimal", + "output": { + "debug": true + } + }, + { + "name": "verbose", + "inherits": "minimal", + "output": { + "verbose": true + } + }, + { + "name": "package-name", + "inherits": "minimal", + "generators": [ + "External" + ], + "packageName": "package-name" + }, + { + "name": "package-version", + "inherits": "minimal", + "generators": [ + "External" + ], + "packageVersion": "1.0" + }, + { + "name": "package-directory", + "inherits": "minimal", + "packageDirectory": "${sourceDir}/build/default/package-directory" + }, + { + "name": "vendor-name", + "inherits": "minimal", + "generators": [ + "External" + ], + "variables": { + "CPACK_EXTERNAL_PACKAGE_SCRIPT": "${sourceDir}/build/default/external_package.cmake" + }, + "vendorName": "some-vendor" + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsPackage/ListPresets-package-x-stdout.txt b/Tests/RunCMake/CMakePresetsPackage/ListPresets-package-x-stdout.txt new file mode 100644 index 0000000..307ec0a --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/ListPresets-package-x-stdout.txt @@ -0,0 +1,4 @@ +^Available package presets: + + "default" + "with-description" - With Description$ diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake b/Tests/RunCMake/CMakePresetsPackage/ListPresets.cmake index e69de29..e69de29 100644 --- a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON.cmake +++ b/Tests/RunCMake/CMakePresetsPackage/ListPresets.cmake diff --git a/Tests/RunCMake/CMakePresetsPackage/ListPresets.json.in b/Tests/RunCMake/CMakePresetsPackage/ListPresets.json.in new file mode 100644 index 0000000..5f3cf48 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/ListPresets.json.in @@ -0,0 +1,20 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default" + } + ], + "packagePresets": [ + { + "name": "default", + "configurePreset": "default" + }, + { + "name": "with-description", + "displayName": "With Description", + "description": "This preset has a description", + "configurePreset": "default" + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake new file mode 100644 index 0000000..269fb6e --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/RunCMakeTest.cmake @@ -0,0 +1,102 @@ +include(RunCMake) + +# Presets do not support legacy VS generator name architecture suffix. +if(RunCMake_GENERATOR MATCHES "^(Visual Studio [0-9]+ [0-9]+) ") + set(RunCMake_GENERATOR "${CMAKE_MATCH_1}") +endif() + +function(run_cmake_package_presets name CMakePresetsPackage_CONFIGURE_PRESETS CMakePresetsPackage_BUILD_PRESETS CMakePresetsPackage_PACKAGE_PRESETS) + set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}") + set(RunCMake_TEST_BINARY_DIR "${RunCMake_TEST_SOURCE_DIR}/build") + set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}") + + set(RunCMake_TEST_NO_CLEAN TRUE) + + file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + set(CASE_NAME "${name}") + set(CASE_SOURCE_DIR "${RunCMake_SOURCE_DIR}") + configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY) + + if(NOT CMakePresetsPackage_FILE) + set(CMakePresetsPackage_FILE "${RunCMake_SOURCE_DIR}/${name}.json.in") + endif() + if(EXISTS "${CMakePresetsPackage_FILE}") + configure_file("${CMakePresetsPackage_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" @ONLY) + endif() + + if(NOT CMakeUserPresets_FILE) + set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/${name}User.json.in") + endif() + if(EXISTS "${CMakeUserPresets_FILE}") + configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY) + endif() + + foreach(ASSET ${CMakePresetsPackage_ASSETS}) + configure_file("${RunCMake_SOURCE_DIR}/${ASSET}" "${RunCMake_TEST_SOURCE_DIR}" COPYONLY) + endforeach() + + if (NOT CMakePresetsPackage_NO_CONFIGURE) + foreach(CONFIGURE_PRESET ${CMakePresetsPackage_CONFIGURE_PRESETS}) + run_cmake_command("${name}-configure-${CONFIGURE_PRESET}" + "${CMAKE_COMMAND}" "--preset" "${CONFIGURE_PRESET}") + endforeach() + endif() + + if (NOT CMakePresetsPackage_NO_BUILD) + foreach(BUILD_PRESET ${CMakePresetsPackage_BUILD_PRESETS}) + run_cmake_command("${name}-build-${BUILD_PRESET}" + "${CMAKE_COMMAND}" "--build" "--preset" "${BUILD_PRESET}") + endforeach() + endif() + + set(eq 0) + foreach(PACKAGE_PRESET ${CMakePresetsPackage_PACKAGE_PRESETS}) + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages") + + if (EXISTS "${RunCMake_SOURCE_DIR}/${name}-package-${PACKAGE_PRESET}-check.cmake") + set(RunCMake-check-file "${name}-package-${PACKAGE_PRESET}-check.cmake") + else() + set(RunCMake-check-file "check.cmake") + endif() + + if(eq) + run_cmake_command(${name}-package-${PACKAGE_PRESET} + ${CMAKE_CPACK_COMMAND} "--preset=${PACKAGE_PRESET}" ${ARGN}) + set(eq 0) + else() + run_cmake_command(${name}-package-${PACKAGE_PRESET} + ${CMAKE_CPACK_COMMAND} "--preset" "${PACKAGE_PRESET}" ${ARGN}) + set(eq 1) + endif() + endforeach() +endfunction() + +function(check_cpack_packages generators contents) + include("${RunCMake_TEST_BINARY_DIR}/default/CPackConfig.cmake") + + set(cpack_dir "${RunCMake_TEST_BINARY_DIR}/default/_CPack_Packages/${CPACK_TOPLEVEL_TAG}") + file(GLOB dirs RELATIVE "${cpack_dir}" "${cpack_dir}/*") + if(NOT dirs STREQUAL generators) + string(APPEND RunCMake_TEST_FAILED "Expected CPack generators: ${generators}\nActual CPack generators: ${dirs}\n") + endif() + + if(contents) + foreach(dir IN LISTS dirs) + set(env_file "${cpack_dir}/${dir}/${CPACK_PACKAGE_FILE_NAME}/env.txt") + file(READ "${env_file}" actual_contents) + if(NOT contents STREQUAL actual_contents) + string(REPLACE "\n" "\n " contents_formatted "${contents}") + string(REPLACE "\n" "\n " actual_contents_formatted "${actual_contents}") + string(APPEND RunCMake_TEST_FAILED "Expected contents of ${env_file}:\n ${contents_formatted}\nActual contents:\n ${actual_contents_formatted}\n") + endif() + endforeach() + endif() + + set(RunCMake_TEST_FAILED ${RunCMake_TEST_FAILED} PARENT_SCOPE) +endfunction() + +run_cmake_package_presets(UnsupportedVersion "x" "" "") +run_cmake_package_presets(Good "default" "build-default-debug" "no-environment;with-environment;generators;configurations;variables;config-file;debug;verbose;package-name;package-version;package-directory;vendor-name") +run_cmake_package_presets(ListPresets "default" "" "x" "--list-presets") diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-result.txt b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-result.txt +++ b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-result.txt diff --git a/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt new file mode 100644 index 0000000..4c461e3 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion-configure-x-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion: File version must be 6 or higher for package preset support$ diff --git a/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion.json.in b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion.json.in new file mode 100644 index 0000000..e5f7240 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/UnsupportedVersion.json.in @@ -0,0 +1,4 @@ +{ + "version": 5, + "packagePresets": [] +} diff --git a/Tests/RunCMake/CMakePresetsPackage/check.cmake b/Tests/RunCMake/CMakePresetsPackage/check.cmake new file mode 100644 index 0000000..e79c4f1 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsPackage/check.cmake @@ -0,0 +1,3 @@ +set(CMakePresets_VALIDATE_SCRIPT_PATH "${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.py") +include("${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.cmake") +include("${RunCMake_SOURCE_DIR}/../CMakePresets/check.cmake") diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-outputJUnit-check.cmake b/Tests/RunCMake/CMakePresetsTest/Good-test-outputJUnit-check.cmake new file mode 100644 index 0000000..e1788cb --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/Good-test-outputJUnit-check.cmake @@ -0,0 +1,4 @@ +include("${CMAKE_CURRENT_LIST_DIR}/check.cmake") +if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/default/output.xml") + string(APPEND RunCMake_TEST_FAILED "Expected ${RunCMake_TEST_BINARY_DIR}/default/output.xml to exist but it does not\n") +endif() diff --git a/Tests/RunCMake/CMakePresetsTest/Good-test-outputLog-check.cmake b/Tests/RunCMake/CMakePresetsTest/Good-test-outputLog-check.cmake new file mode 100644 index 0000000..e860d42 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/Good-test-outputLog-check.cmake @@ -0,0 +1,4 @@ +include("${CMAKE_CURRENT_LIST_DIR}/check.cmake") +if(NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/default/output.log") + string(APPEND RunCMake_TEST_FAILED "Expected ${RunCMake_TEST_BINARY_DIR}/default/output.log to exist but it does not\n") +endif() diff --git a/Tests/RunCMake/CMakePresetsTest/Good.json.in b/Tests/RunCMake/CMakePresetsTest/Good.json.in index d484a19..a4b875a 100644 --- a/Tests/RunCMake/CMakePresetsTest/Good.json.in +++ b/Tests/RunCMake/CMakePresetsTest/Good.json.in @@ -1,5 +1,5 @@ { - "version": 5, + "version": 6, "configurePresets": [ { "name": "default", @@ -171,6 +171,20 @@ "execution": { "showOnly": "human" } + }, + { + "name": "outputLog", + "inherits": "minimal", + "output": { + "outputLogFile": "${sourceDir}/build/default/output.log" + } + }, + { + "name": "outputJUnit", + "inherits": "minimal", + "output": { + "outputJUnitFile": "${sourceDir}/build/default/output.xml" + } } ] } diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-result.txt b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-result.txt +++ b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-result.txt diff --git a/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt new file mode 100644 index 0000000..acd5785 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported-test-x-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported: File version must be 6 or higher for CTest JUnit output support$ diff --git a/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported.json.in b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported.json.in new file mode 100644 index 0000000..93f6b0c --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/OutputJUnitUnsupported.json.in @@ -0,0 +1,17 @@ +{ + "version": 5, + "configurePresets": [ + { + "name": "default" + } + ], + "testPresets": [ + { + "name": "unsupported", + "configurePreset": "default", + "output": { + "outputJUnitFile": "junit.xml" + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake index bec0dd94..1c7b836 100644 --- a/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsTest/RunCMakeTest.cmake @@ -78,7 +78,7 @@ set(CMakePresetsTest_ASSETS "Good-indexFile.txt") set(GoodTestPresets "minimal;defaults;noEnvironment;withEnvironment" "config-debug;config-release" - "exclude;index;indexFile;showOnly") + "exclude;index;indexFile;showOnly;outputLog;outputJUnit") run_cmake_test_presets(Good "default" "" @@ -105,6 +105,8 @@ run_cmake_test_presets(Invalid "" "" "hidden;vendorMacro") set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) run_cmake_test_presets(PresetsUnsupported "" "" "x") run_cmake_test_presets(ConditionFuture "" "" "x") +run_cmake_test_presets(TestOutputTruncationUnsupported "" "" "x") +run_cmake_test_presets(OutputJUnitUnsupported "" "" "x") set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) run_cmake_test_presets(ConfigurePresetUnreachable "" "" "x") set(CMakePresetsTest_NO_CONFIGURE 0) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-result.txt b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-result.txt +++ b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-result.txt diff --git a/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt new file mode 100644 index 0000000..90ea7c3 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported-test-x-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported: File version must be 5 or higher for testOutputTruncation preset support\.$ diff --git a/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported.json.in b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported.json.in new file mode 100644 index 0000000..c116039 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsTest/TestOutputTruncationUnsupported.json.in @@ -0,0 +1,17 @@ +{ + "version": 4, + "configurePresets": [ + { + "name": "default" + } + ], + "testPresets": [ + { + "name": "default", + "configurePreset": "default", + "output": { + "testOutputTruncation": "tail" + } + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt new file mode 100644 index 0000000..45a4fb7 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-result.txt @@ -0,0 +1 @@ +8 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt new file mode 100644 index 0000000..0690c69 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stderr.txt @@ -0,0 +1,4 @@ +^Errors while running CTest +Output from these tests are in: [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode/build/Testing/Temporary/LastTest\.log +Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely\.$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt new file mode 100644 index 0000000..2f23f88 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode-stdout.txt @@ -0,0 +1,17 @@ +^Executing workflow step 1 of 4: configure preset "default" + +.*Testing the configure step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode/build.* + +Executing workflow step 2 of 4: build preset "default" + +.*Testing the build step at [^ +]*[\\/]Tests[\\/]RunCMake[\\/]CMakePresetsWorkflow[\\/]BadExitCode[\\/]build.* + +Executing workflow step 3 of 4: test preset "default" + +.*Testing the test step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode/build.* + +The following tests FAILED: +.* +1 - EchoTest \(Failed\)$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake new file mode 100644 index 0000000..10b46e3 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCode.cmake @@ -0,0 +1,8 @@ +message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}") + +add_custom_target(echo_test ALL COMMAND ${CMAKE_COMMAND} -E echo "Testing the build step at ${CMAKE_BINARY_DIR}") + +enable_testing() +add_test(NAME EchoTest COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_LIST_DIR}/BadExitCodeTest.cmake") + +include(CPack) diff --git a/Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake new file mode 100644 index 0000000..59f683e --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/BadExitCodeTest.cmake @@ -0,0 +1 @@ +message(FATAL_ERROR " Testing the test step at ${CMAKE_BINARY_DIR}") diff --git a/Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in b/Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in new file mode 100644 index 0000000..129184a --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/CMakeLists.txt.in @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.19) +project("@CASE_NAME@" NONE) +include("@CASE_SOURCE_DIR@/@CASE_NAME@.cmake") diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-result.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-result.txt diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt new file mode 100644 index 0000000..22ca94d --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in new file mode 100644 index 0000000..0864149 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/ConfigureStepMismatch.json.in @@ -0,0 +1,32 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default" + }, + { + "name": "mismatch" + } + ], + "buildPresets": [ + { + "name": "mismatch", + "configurePreset": "mismatch" + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "mismatch" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-result.txt index e69de29..e69de29 100644 --- a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-OFF.cmake +++ b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-result.txt diff --git a/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt new file mode 100644 index 0000000..cbfee5a --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in new file mode 100644 index 0000000..2c121a8 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/FirstStepNotConfigure.json.in @@ -0,0 +1,27 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@" + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default" + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "build", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt new file mode 100644 index 0000000..a04d7ea --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/Good-stdout.txt @@ -0,0 +1,19 @@ +^Executing workflow step 1 of 4: configure preset "default" + +.*Testing the configure step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/Good/build.* + +Executing workflow step 2 of 4: build preset "default" + +.*Testing the build step at [^ +]*[\\/]Tests[\\/]RunCMake[\\/]CMakePresetsWorkflow[\\/]Good[\\/]build.* + +Executing workflow step 3 of 4: test preset "default" + +.*Testing the test step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/Good/build.* + +Executing workflow step 4 of 4: package preset "default" + +.*Testing the package step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/Good/build.* diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Good.cmake b/Tests/RunCMake/CMakePresetsWorkflow/Good.cmake new file mode 100644 index 0000000..31ce7ff --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/Good.cmake @@ -0,0 +1,8 @@ +message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}") + +add_custom_target(echo_test ALL COMMAND ${CMAKE_COMMAND} -E echo "Testing the build step at ${CMAKE_BINARY_DIR}") + +enable_testing() +add_test(NAME EchoTest COMMAND ${CMAKE_COMMAND} -E echo "Testing the test step at ${CMAKE_BINARY_DIR}") + +include(CPack) diff --git a/Tests/RunCMake/CMakePresetsWorkflow/Good.json.in b/Tests/RunCMake/CMakePresetsWorkflow/Good.json.in new file mode 100644 index 0000000..87e2936 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/Good.json.in @@ -0,0 +1,87 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@" + } + ], + "buildPresets": [ + { + "name": "default", + "configurePreset": "default", + "configuration": "Debug" + } + ], + "testPresets": [ + { + "name": "default", + "configurePreset": "default", + "output": { + "verbosity": "verbose" + }, + "configuration": "Debug" + } + ], + "packagePresets": [ + { + "name": "default", + "configurePreset": "default", + "generators": [ + "External" + ], + "variables": { + "CPACK_EXTERNAL_PACKAGE_SCRIPT": "${sourceDir}/cpack_staging.cmake" + }, + "configurations": ["Debug"] + } + ], + "workflowPresets": [ + { + "name": "Good", + "displayName": "Good Workflow Preset", + "description": "This workflow preset works properly.", + "vendor": {}, + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + }, + { + "type": "package", + "name": "default" + } + ] + }, + { + "name": "BadExitCode", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "build", + "name": "default" + }, + { + "type": "test", + "name": "default" + }, + { + "type": "package", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt new file mode 100644 index 0000000..1014915 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser-stdout.txt @@ -0,0 +1,2 @@ +-- Testing the configure step at [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/GoodUser/build diff --git a/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake new file mode 100644 index 0000000..9143e00 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.cmake @@ -0,0 +1 @@ +message(STATUS "Testing the configure step at ${CMAKE_BINARY_DIR}") diff --git a/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in new file mode 100644 index 0000000..e71b4ea --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/GoodUser.json.in @@ -0,0 +1,14 @@ +{ + "version": 6, + "workflowPresets": [ + { + "name": "GoodUser", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt new file mode 100644 index 0000000..57f30a4 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets-stdout.txt @@ -0,0 +1,4 @@ +^Available workflow presets: + + "default" + "with-description" - With Description$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in new file mode 100644 index 0000000..9a7d5a6 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/ListPresets.json.in @@ -0,0 +1,30 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default" + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + }, + { + "name": "with-description", + "displayName": "With Description", + "description": "This preset has a description.", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-result.txt +++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-result.txt diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt new file mode 100644 index 0000000..049ed6b --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in new file mode 100644 index 0000000..2757197 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NoWorkflowSteps.json.in @@ -0,0 +1,9 @@ +{ + "version": 6, + "workflowPresets": [ + { + "name": "default", + "steps": [] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt new file mode 100644 index 0000000..c522b84 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in new file mode 100644 index 0000000..235398b --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/NonexistentStep.json.in @@ -0,0 +1,14 @@ +{ + "version": 6, + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake new file mode 100644 index 0000000..b89a11a --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/RunCMakeTest.cmake @@ -0,0 +1,79 @@ +include(RunCMake) + +# Presets do not support legacy VS generator name architecture suffix. +if(RunCMake_GENERATOR MATCHES "^(Visual Studio [0-9]+ [0-9]+) ") + set(RunCMake_GENERATOR "${CMAKE_MATCH_1}") +endif() + +function(run_cmake_workflow_presets name) + set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}") + set(RunCMake_TEST_BINARY_DIR "${RunCMake_TEST_SOURCE_DIR}/build") + set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}") + + set(RunCMake_TEST_NO_CLEAN TRUE) + + file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}") + + set(CASE_NAME "${name}") + set(CASE_SOURCE_DIR "${RunCMake_SOURCE_DIR}") + configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY) + + if(NOT CMakePresets_FILE) + set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/${name}.json.in") + endif() + if(EXISTS "${CMakePresets_FILE}") + configure_file("${CMakePresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" @ONLY) + endif() + + if(NOT CMakeUserPresets_FILE) + set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/${name}User.json.in") + endif() + if(EXISTS "${CMakeUserPresets_FILE}") + configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY) + endif() + + foreach(ASSET ${CMakePresets_ASSETS}) + configure_file("${RunCMake_SOURCE_DIR}/${ASSET}.in" "${RunCMake_TEST_SOURCE_DIR}/${ASSET}" @ONLY) + endforeach() + + if(EXISTS "${RunCMake_SOURCE_DIR}/${name}-check.cmake") + set(RunCMake-check-file "${name}-check.cmake") + else() + set(RunCMake-check-file "check.cmake") + endif() + + if(eq) + set(eq 0 PARENT_SCOPE) + set(preset_arg "--preset=${name}") + else() + set(eq 1 PARENT_SCOPE) + set(preset_arg "--preset" "${name}") + endif() + run_cmake_command("${name}" "${CMAKE_COMMAND}" "--workflow" ${preset_arg} ${ARGN}) +endfunction() + +set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) +run_cmake_workflow_presets(UnsupportedVersion) +set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) +run_cmake_workflow_presets(NoWorkflowSteps) +run_cmake_workflow_presets(FirstStepNotConfigure) +run_cmake_workflow_presets(SecondStepConfigure) +run_cmake_workflow_presets(NonexistentStep) +run_cmake_workflow_presets(UnreachableStep) +run_cmake_workflow_presets(WorkflowStepHidden) +run_cmake_workflow_presets(WorkflowStepDisabled) +run_cmake_workflow_presets(WorkflowStepInvalidMacro) +run_cmake_workflow_presets(ConfigureStepMismatch) + +set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Good.json.in") +set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/GoodUser.json.in") +set(CMakePresets_ASSETS cpack_staging.cmake) +run_cmake_workflow_presets(Good) +run_cmake_workflow_presets(GoodUser) +run_cmake_workflow_presets(BadExitCode) +unset(CMakePresets_FILE) +unset(CMakeUserPresets_FILE) +unset(CMakePresets_ASSETS) + +run_cmake_workflow_presets(ListPresets --list-presets) diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt new file mode 100644 index 0000000..b0ad7d5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure: Invalid workflow steps$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in new file mode 100644 index 0000000..44e1582 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/SecondStepConfigure.json.in @@ -0,0 +1,25 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@" + } + ], + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + }, + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt new file mode 100644 index 0000000..425e719 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep: Workflow step is unreachable from preset's file$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in new file mode 100644 index 0000000..235398b --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStep.json.in @@ -0,0 +1,14 @@ +{ + "version": 6, + "workflowPresets": [ + { + "name": "default", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in new file mode 100644 index 0000000..39b6835 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnreachableStepUser.json.in @@ -0,0 +1,8 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default" + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt new file mode 100644 index 0000000..5cf01aa --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Could not read presets from [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion: File version must be 6 or higher for workflow preset support$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in new file mode 100644 index 0000000..4ebaa8e --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/UnsupportedVersion.json.in @@ -0,0 +1,4 @@ +{ + "version": 5, + "workflowPresets": [] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt new file mode 100644 index 0000000..b598b27 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Cannot use disabled configure preset in [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled: "default"$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in new file mode 100644 index 0000000..a3b6783 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepDisabled.json.in @@ -0,0 +1,23 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "condition": { + "type": "const", + "value": false + } + } + ], + "workflowPresets": [ + { + "name": "WorkflowStepDisabled", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt new file mode 100644 index 0000000..838ded5 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden-stderr.txt @@ -0,0 +1,2 @@ +^CMake Error: Cannot use hidden configure preset in [^ +]*/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden: "default"$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in new file mode 100644 index 0000000..07c4105 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepHidden.json.in @@ -0,0 +1,20 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "hidden": true + } + ], + "workflowPresets": [ + { + "name": "WorkflowStepHidden", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt new file mode 100644 index 0000000..f132a93 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Could not evaluate configure preset "default": Invalid macro expansion$ diff --git a/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in new file mode 100644 index 0000000..6aec0e3 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/WorkflowStepInvalidMacro.json.in @@ -0,0 +1,20 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "binaryDir": "$vendor{invalidMacro}" + } + ], + "workflowPresets": [ + { + "name": "WorkflowStepInvalidMacro", + "steps": [ + { + "type": "configure", + "name": "default" + } + ] + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsWorkflow/check.cmake b/Tests/RunCMake/CMakePresetsWorkflow/check.cmake new file mode 100644 index 0000000..e79c4f1 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/check.cmake @@ -0,0 +1,3 @@ +set(CMakePresets_VALIDATE_SCRIPT_PATH "${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.py") +include("${RunCMake_SOURCE_DIR}/../CMakePresets/validate_schema.cmake") +include("${RunCMake_SOURCE_DIR}/../CMakePresets/check.cmake") diff --git a/Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in b/Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in new file mode 100644 index 0000000..4030dfb --- /dev/null +++ b/Tests/RunCMake/CMakePresetsWorkflow/cpack_staging.cmake.in @@ -0,0 +1 @@ +message(STATUS "Testing the package step at @RunCMake_TEST_BINARY_DIR@") diff --git a/Tests/RunCMake/CPack/DEB/Helpers.cmake b/Tests/RunCMake/CPack/DEB/Helpers.cmake index 9b98ed4..8904c69 100644 --- a/Tests/RunCMake/CPack/DEB/Helpers.cmake +++ b/Tests/RunCMake/CPack/DEB/Helpers.cmake @@ -97,7 +97,7 @@ function(getMissingShlibsErrorExtra FILE RESULT_VAR) string(APPEND error_extra "; errors \"${deb_install_files_errors}\"") endif() - if(READELF_EXECUTABLE) + if(CPACK_READELF_EXECUTABLE) string(APPEND error_extra "; readelf \"\n") # Only dynamically linked ELF files are included @@ -106,7 +106,7 @@ function(getMissingShlibsErrorExtra FILE RESULT_VAR) if(_FILE MATCHES "ELF.*shared object") string(REGEX MATCH "(^.*):" _FILE_NAME "${_FILE}") - execute_process(COMMAND ${READELF_EXECUTABLE} -d "${CMAKE_MATCH_1}" + execute_process(COMMAND ${CPACK_READELF_EXECUTABLE} -d "${CMAKE_MATCH_1}" WORKING_DIRECTORY "${CPACK_TEMPORARY_DIRECTORY}" RESULT_VARIABLE result OUTPUT_VARIABLE output diff --git a/Tests/RunCMake/CPack/DEB/Prerequirements.cmake b/Tests/RunCMake/CPack/DEB/Prerequirements.cmake index 60d02e7..3b02579 100644 --- a/Tests/RunCMake/CPack/DEB/Prerequirements.cmake +++ b/Tests/RunCMake/CPack/DEB/Prerequirements.cmake @@ -14,9 +14,9 @@ function(get_test_prerequirements found_var config_file) endif() # optional tool for some tests - find_program(READELF_EXECUTABLE NAMES readelf) - if(READELF_EXECUTABLE) + find_program(CPACK_READELF_EXECUTABLE NAMES readelf) + if(CPACK_READELF_EXECUTABLE) file(APPEND "${config_file}" - "\nset(READELF_EXECUTABLE \"${READELF_EXECUTABLE}\")") + "\nset(CPACK_READELF_EXECUTABLE \"${CPACK_READELF_EXECUTABLE}\")") endif() endfunction() diff --git a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake index e95cd15..a4741ba 100644 --- a/Tests/RunCMake/CPack/RPM/Prerequirements.cmake +++ b/Tests/RunCMake/CPack/RPM/Prerequirements.cmake @@ -15,9 +15,9 @@ function(get_test_prerequirements found_var config_file) endif() # optional tool for some tests - find_program(OBJDUMP_EXECUTABLE objdump) - if(OBJDUMP_EXECUTABLE) + find_program(CPACK_OBJDUMP_EXECUTABLE objdump) + if(CPACK_OBJDUMP_EXECUTABLE) file(APPEND "${config_file}" - "\nset(OBJDUMP_EXECUTABLE \"${OBJDUMP_EXECUTABLE}\")") + "\nset(CPACK_OBJDUMP_EXECUTABLE \"${CPACK_OBJDUMP_EXECUTABLE}\")") endif() endfunction() diff --git a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake index be44b2e..b0bfc9d 100644 --- a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake +++ b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS/DEB-Prerequirements.cmake @@ -1,7 +1,7 @@ function(get_test_prerequirements found_var config_file) include(${config_file}) - if(READELF_EXECUTABLE) + if(CPACK_READELF_EXECUTABLE) set(${found_var} true PARENT_SCOPE) endif() endfunction() diff --git a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake index be44b2e..b0bfc9d 100644 --- a/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake +++ b/Tests/RunCMake/CPack/tests/GENERATE_SHLIBS_LDCONFIG/DEB-Prerequirements.cmake @@ -1,7 +1,7 @@ function(get_test_prerequirements found_var config_file) include(${config_file}) - if(READELF_EXECUTABLE) + if(CPACK_READELF_EXECUTABLE) set(${found_var} true PARENT_SCOPE) endif() endfunction() diff --git a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake index 90cfe44..f5df8a2 100644 --- a/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake +++ b/Tests/RunCMake/CPack/tests/INSTALL_SCRIPTS/RPM-Prerequirements.cmake @@ -2,7 +2,7 @@ function(get_test_prerequirements found_var config_file) if(SUBTEST_SUFFIX MATCHES ".*single_debug_info") include(${config_file}) - if(OBJDUMP_EXECUTABLE) + if(CPACK_OBJDUMP_EXECUTABLE) set(${found_var} true PARENT_SCOPE) endif() else() diff --git a/Tests/RunCMake/CTestTimeout/TestTimeout.c b/Tests/RunCMake/CTestTimeout/TestTimeout.c index 5a008a7..0d534fc 100644 --- a/Tests/RunCMake/CTestTimeout/TestTimeout.c +++ b/Tests/RunCMake/CTestTimeout/TestTimeout.c @@ -1,6 +1,7 @@ #if defined(_WIN32) # include <windows.h> #else +# include <sched.h> # include <unistd.h> #endif diff --git a/Tests/RunCMake/CUDA_architectures/architectures-suffix-stderr.txt b/Tests/RunCMake/CUDA_architectures/architectures-suffix-stderr.txt index 7b6eb53..ce40a7a 100644 --- a/Tests/RunCMake/CUDA_architectures/architectures-suffix-stderr.txt +++ b/Tests/RunCMake/CUDA_architectures/architectures-suffix-stderr.txt @@ -1,4 +1,4 @@ ^(CMake Warning in [^ -]*/Tests/RunCMake/CUDA_architectures/architectures-suffix-build/CMakeFiles/CMakeTmp/CMakeLists.txt: +]*/Tests/RunCMake/CUDA_architectures/architectures-suffix-build/CMakeFiles/CMakeScratch/TryCompile-[^/]*/CMakeLists.txt: Clang doesn't support disabling CUDA real code generation. *)*$ diff --git a/Tests/RunCMake/CXXModules/CMakeLists.txt b/Tests/RunCMake/CXXModules/CMakeLists.txt new file mode 100644 index 0000000..708d92c --- /dev/null +++ b/Tests/RunCMake/CXXModules/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.23) +project(${RunCMake_TEST} NONE) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046") + +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake new file mode 100644 index 0000000..cb6f6bd --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-check.cmake @@ -0,0 +1,40 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/export-modules-targets.cmake" export_script) + +if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules\.cmake"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property script inclusion") +endif () + +file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules.cmake" trampoline_script) + +if (RunCMake_GENERATOR_IS_MULTI_CONFIG) + if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-[^.]*\.cmake" OPTIONAL\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property per-config script inclusion(s)") + endif () +else () + if (NOT trampoline_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-[^.]*\.cmake"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property per-config script inclusion(s)") + endif () +endif () + +set(any_exists 0) +foreach (config IN ITEMS noconfig Debug Release RelWithDebInfo MinSizeRel) + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-${config}.cmake") + continue () + endif () + set(any_exists 1) + + file(READ "${RunCMake_TEST_BINARY_DIR}/lib/cmake/export-modules/cxx-modules/cxx-modules-${config}.cmake" config_script) + + if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)") + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module per-target property script inclusion") + endif () +endforeach () + +if (NOT any_exists) + list(APPEND RunCMake_TEST_FAILED + "No per-configuration target files exist.") +endif () diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt new file mode 100644 index 0000000..c05b0b4 --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at ExportBuildCxxModules.cmake:6 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake b/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake new file mode 100644 index 0000000..850f8dc --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportBuildCxxModules.cmake @@ -0,0 +1,22 @@ +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(export-modules) +target_sources(export-modules + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(export-modules + PRIVATE + cxx_std_20) +set_property(TARGET export-modules + PROPERTY EXPORT_NAME export-name) + +install(TARGETS export-modules + EXPORT exp + FILE_SET fs DESTINATION "include/cxx/export-modules") + +export(EXPORT exp + FILE "${CMAKE_BINARY_DIR}/lib/cmake/export-modules/export-modules-targets.cmake" + CXX_MODULES_DIRECTORY "cxx-modules") diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake new file mode 100644 index 0000000..9e83fd8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-check.cmake @@ -0,0 +1,35 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/exp.cmake" export_script) + +if (NOT export_script MATCHES [[include\("\${CMAKE_CURRENT_LIST_DIR}/cxx-modules/cxx-modules\.cmake"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property script inclusion") +endif () + +file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules.cmake" trampoline_script) + +if (NOT trampoline_script MATCHES [[file\(GLOB _cmake_cxx_module_includes "\${CMAKE_CURRENT_LIST_DIR}/cxx-modules-\*\.cmake"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module property per-config script inclusion(s)") +endif () + +set(any_exists 0) +foreach (config IN ITEMS noconfig Debug Release RelWithDebInfo MinSizeRel) + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-${config}.cmake") + continue () + endif () + set(any_exists 1) + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/Export/eee57a7e91412f1be699e9b63fa9d601/cxx-modules/cxx-modules-${config}.cmake" config_script) + + if (NOT config_script MATCHES "include\\(\"\\\${CMAKE_CURRENT_LIST_DIR}/target-export-name-${config}\\.cmake\"\\)") + list(APPEND RunCMake_TEST_FAILED + "Could not find C++ module per-target property script inclusion") + endif () +endforeach () + +if (NOT any_exists) + list(APPEND RunCMake_TEST_FAILED + "No per-configuration target files exist.") +endif () + +string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}") diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt new file mode 100644 index 0000000..4fe27a9 --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at ExportInstallCxxModules.cmake:6 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake b/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake new file mode 100644 index 0000000..234a4b5 --- /dev/null +++ b/Tests/RunCMake/CXXModules/ExportInstallCxxModules.cmake @@ -0,0 +1,22 @@ +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(export-modules) +target_sources(export-modules + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(export-modules + PRIVATE + cxx_std_20) +set_property(TARGET export-modules + PROPERTY EXPORT_NAME export-name) + +install(TARGETS export-modules + EXPORT exp + FILE_SET fs DESTINATION "include/cxx/export-modules") + +install(EXPORT exp + DESTINATION "lib/cmake/export-modules" + CXX_MODULES_DIRECTORY "cxx-modules") diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt new file mode 100644 index 0000000..d573a02 --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface-stderr.txt @@ -0,0 +1,12 @@ +CMake Warning \(dev\) at FileSetModuleHeaderUnitsInterface.cmake:2 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error at FileSetModuleHeaderUnitsInterface.cmake:2 \(target_sources\): + target_sources File set TYPEs "CXX_MODULES" and "CXX_MODULE_HEADER_UNITS" + may not have "INTERFACE" visibility +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake new file mode 100644 index 0000000..03ca17e --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterface.cmake @@ -0,0 +1,8 @@ +add_library(module-header) +target_sources(module-header + INTERFACE + FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES + sources/module-header.h) +target_compile_features(module-header + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt new file mode 100644 index 0000000..1b4ba5d --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported-stderr.txt @@ -0,0 +1,6 @@ +CMake Warning \(dev\) at FileSetModuleHeaderUnitsInterfaceImported.cmake:2 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake new file mode 100644 index 0000000..9ff5606 --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsInterfaceImported.cmake @@ -0,0 +1,8 @@ +add_library(module-header SHARED IMPORTED) +target_sources(module-header + INTERFACE + FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES + sources/module-header.h) +target_compile_features(module-header + INTERFACE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt new file mode 100644 index 0000000..a7ac88e --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at FileSetModuleHeaderUnitsPrivate.cmake:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake new file mode 100644 index 0000000..ebf9853 --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPrivate.cmake @@ -0,0 +1,13 @@ +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(module-header + sources/cxx-anchor.cxx) +target_sources(module-header + PRIVATE + FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES + sources/module-header.h) +target_compile_features(module-header + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt new file mode 100644 index 0000000..a5b4ede --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at FileSetModuleHeaderUnitsPublic.cmake:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake new file mode 100644 index 0000000..3dfccbb5 --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModuleHeaderUnitsPublic.cmake @@ -0,0 +1,13 @@ +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(module-header + sources/cxx-anchor.cxx) +target_sources(module-header + PUBLIC + FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES + sources/module-header.h) +target_compile_features(module-header + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModulesInterface-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt new file mode 100644 index 0000000..81a35e8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModulesInterface-stderr.txt @@ -0,0 +1,12 @@ +CMake Warning \(dev\) at FileSetModulesInterface.cmake:2 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error at FileSetModulesInterface.cmake:2 \(target_sources\): + target_sources File set TYPEs "CXX_MODULES" and "CXX_MODULE_HEADER_UNITS" + may not have "INTERFACE" visibility +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake b/Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake new file mode 100644 index 0000000..24cec3e --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModulesInterface.cmake @@ -0,0 +1,8 @@ +add_library(module) +target_sources(module + INTERFACE + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(module + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt new file mode 100644 index 0000000..4420bbc --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported-stderr.txt @@ -0,0 +1,6 @@ +CMake Warning \(dev\) at FileSetModulesInterfaceImported.cmake:2 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake new file mode 100644 index 0000000..6640ae9 --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModulesInterfaceImported.cmake @@ -0,0 +1,8 @@ +add_library(module SHARED IMPORTED) +target_sources(module + INTERFACE + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(module + INTERFACE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt new file mode 100644 index 0000000..03e06cc --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModulesPrivate-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at FileSetModulesPrivate.cmake:6 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake b/Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake new file mode 100644 index 0000000..ca18982 --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModulesPrivate.cmake @@ -0,0 +1,12 @@ +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(module) +target_sources(module + PRIVATE + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(module + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt b/Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt new file mode 100644 index 0000000..0c110c3 --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModulesPublic-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at FileSetModulesPublic.cmake:6 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake b/Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake new file mode 100644 index 0000000..58de174 --- /dev/null +++ b/Tests/RunCMake/CXXModules/FileSetModulesPublic.cmake @@ -0,0 +1,12 @@ +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(module) +target_sources(module + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(module + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/InstallBMI-check.cmake b/Tests/RunCMake/CXXModules/InstallBMI-check.cmake new file mode 100644 index 0000000..f891c80 --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMI-check.cmake @@ -0,0 +1,24 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script) + +if (NOT install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi" OR NOT CMAKE_INSTALL_COMPONENT\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find BMI install script component for `bmi`") +endif () + +if (NOT install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find BMI install script inclusion") +endif () + +if (NOT install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi-optional"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find BMI install script component for `bmi-optional`") +endif () + +if (NOT install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi-only-debug" OR NOT CMAKE_INSTALL_COMPONENT\) + if\(CMAKE_INSTALL_CONFIG_NAME MATCHES "\^\(\[Dd\]\[Ee\]\[Bb\]\[Uu\]\[Gg\]\)\$"\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find BMI install script component for `bmi-only-debug`") +endif () + +string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}") diff --git a/Tests/RunCMake/CXXModules/InstallBMI-stderr.txt b/Tests/RunCMake/CXXModules/InstallBMI-stderr.txt new file mode 100644 index 0000000..fc3c7db --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMI-stderr.txt @@ -0,0 +1,6 @@ +CMake Warning \(dev\) at InstallBMI.cmake:8 \(install\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/InstallBMI.cmake b/Tests/RunCMake/CXXModules/InstallBMI.cmake new file mode 100644 index 0000000..f0947b4 --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMI.cmake @@ -0,0 +1,23 @@ +enable_language(CXX) + +add_library(install-bmi) +target_sources(install-bmi + PRIVATE + sources/cxx-anchor.cxx) + +install(TARGETS install-bmi + CXX_MODULES_BMI + DESTINATION "lib/bmi" + COMPONENT "bmi") + +install(TARGETS install-bmi + CXX_MODULES_BMI + DESTINATION "lib/bmi" + EXCLUDE_FROM_ALL + COMPONENT "bmi-optional") + +install(TARGETS install-bmi + CXX_MODULES_BMI + DESTINATION "lib/bmi" + CONFIGURATIONS Debug + COMPONENT "bmi-only-debug") diff --git a/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake new file mode 100644 index 0000000..32a37ad --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-check.cmake @@ -0,0 +1,8 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script) + +if (NOT install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi-generic-args\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]]) + list(APPEND RunCMake_TEST_FAILED + "Could not find BMI install script inclusion") +endif () + +string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}") diff --git a/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt new file mode 100644 index 0000000..44c961f --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs-stderr.txt @@ -0,0 +1,6 @@ +CMake Warning \(dev\) at InstallBMIGenericArgs.cmake:8 \(install\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake new file mode 100644 index 0000000..8f17143 --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMIGenericArgs.cmake @@ -0,0 +1,9 @@ +enable_language(CXX) + +add_library(install-bmi-generic-args) +target_sources(install-bmi-generic-args + PRIVATE + sources/cxx-anchor.cxx) + +install(TARGETS install-bmi-generic-args + DESTINATION "bin") diff --git a/Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake b/Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake new file mode 100644 index 0000000..7d13ef0 --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMIIgnore-check.cmake @@ -0,0 +1,13 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script) + +if (install_script MATCHES [[\(CMAKE_INSTALL_COMPONENT STREQUAL "bmi" OR NOT CMAKE_INSTALL_COMPONENT\)]]) + list(APPEND RunCMake_TEST_FAILED + "Found BMI install script component for `bmi`") +endif () + +if (install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi-ignore\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]]) + list(APPEND RunCMake_TEST_FAILED + "Found BMI install script inclusion") +endif () + +string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}") diff --git a/Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt b/Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt new file mode 100644 index 0000000..d9d2c2d --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMIIgnore-stderr.txt @@ -0,0 +1,6 @@ +CMake Warning \(dev\) at InstallBMIIgnore.cmake:5 \(install\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake b/Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake new file mode 100644 index 0000000..f339511 --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMIIgnore.cmake @@ -0,0 +1,9 @@ +enable_language(CXX) + +add_library(install-bmi-ignore INTERFACE) + +install(TARGETS install-bmi-ignore + CXX_MODULES_BMI + # An empty destination ignores BMI installation. + DESTINATION "" + COMPONENT "bmi") diff --git a/Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake b/Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake new file mode 100644 index 0000000..412e260 --- /dev/null +++ b/Tests/RunCMake/CXXModules/InstallBMINoGenericArgs-check.cmake @@ -0,0 +1,8 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake" install_script) + +if (install_script MATCHES [[include\("[^)]*/CMakeFiles/install-bmi-generic-args\.dir/install-cxx-module-bmi-[^.]*\.cmake" OPTIONAL\)]]) + list(APPEND RunCMake_TEST_FAILED + "Found BMI install script inclusion") +endif () + +string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}") diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake new file mode 100644 index 0000000..0d08c44 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-check.cmake @@ -0,0 +1,34 @@ +include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake") + +if (RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(have_file 0) + foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel) + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-public.dir/${config}/CXXDependInfo.json") + continue () + endif () + set(have_file 1) + + set(CMAKE_BUILD_TYPE "${config}") + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-public.dir/${config}/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-public.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-private.dir/${config}/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-private.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") + endforeach () + + if (NOT have_file) + list(APPEND RunCMake_TEST_FAILED + "No recognized build configurations found.") + endif () +else () + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-public.dir/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-public.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-bmi-install-private.dir/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoBMIInstall-private.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") +endif () diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt new file mode 100644 index 0000000..ebf7be5 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at NinjaDependInfoBMIInstall.cmake:14 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake new file mode 100644 index 0000000..32dc42d --- /dev/null +++ b/Tests/RunCMake/CXXModules/NinjaDependInfoBMIInstall.cmake @@ -0,0 +1,76 @@ +# Fake out that we have dyndep; we only need to generate, not actually build +# here. +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +enable_language(CXX) + +if (NOT CMAKE_GENERATOR MATCHES "Ninja") + message(FATAL_ERROR + "This test requires a 'Ninja' generator to be used.") +endif () + +add_library(ninja-bmi-install-public) +target_sources(ninja-bmi-install-public + PRIVATE + sources/module-impl.cxx + sources/module-internal-part-impl.cxx + sources/module-part-impl.cxx + sources/module-use.cxx + PUBLIC + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/sources" + FILES + sources/module.cxx + sources/module-part.cxx + FILE_SET internal_partitions TYPE CXX_MODULES FILES + sources/module-internal-part.cxx) +target_compile_features(ninja-bmi-install-public + PRIVATE + cxx_std_20) +set_property(TARGET ninja-bmi-install-public + PROPERTY EXPORT_NAME "with-public") + +install(TARGETS ninja-bmi-install-public + FILE_SET modules + DESTINATION "lib/cxx" + COMPONENT "modules" + FILE_SET internal_partitions + DESTINATION "lib/cxx/internals" + COMPONENT "modules-internal" + CXX_MODULES_BMI + DESTINATION "lib/cxx/modules/$<CONFIG>" + COMPONENT "bmi") + +add_library(ninja-bmi-install-private) +target_sources(ninja-bmi-install-private + PRIVATE + sources/module-impl.cxx + sources/module-internal-part-impl.cxx + sources/module-part-impl.cxx + sources/module-use.cxx + PRIVATE + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/sources" + FILES + sources/module.cxx + sources/module-part.cxx + FILE_SET internal_partitions TYPE CXX_MODULES FILES + sources/module-internal-part.cxx) +target_compile_features(ninja-bmi-install-private + PRIVATE + cxx_std_20) +set_property(TARGET ninja-bmi-install-private + PROPERTY EXPORT_NAME "with-private") + +set(CMAKE_INSTALL_MESSAGE LAZY) +install(TARGETS ninja-bmi-install-private + CXX_MODULES_BMI + DESTINATION "lib/cxx/modules/private/$<CONFIG>" + PERMISSIONS + OWNER_READ OWNER_WRITE + GROUP_READ + WORLD_READ + COMPONENT "bmi") diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake new file mode 100644 index 0000000..7720257 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-check.cmake @@ -0,0 +1,34 @@ +include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake") + +if (RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(have_file 0) + foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel) + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/${config}/CXXDependInfo.json") + continue () + endif () + set(have_file 1) + + set(CMAKE_BUILD_TYPE "${config}") + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/${config}/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-public.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-private.dir/${config}/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-private.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") + endforeach () + + if (NOT have_file) + list(APPEND RunCMake_TEST_FAILED + "No recognized build configurations found.") + endif () +else () + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-public.dir/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-public.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-exports-private.dir/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoExport-private.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") +endif () diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt new file mode 100644 index 0000000..e328223 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NinjaDependInfoExport-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at NinjaDependInfoExport.cmake:14 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake new file mode 100644 index 0000000..05e7ef7 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NinjaDependInfoExport.cmake @@ -0,0 +1,85 @@ +# Fake out that we have dyndep; we only need to generate, not actually build +# here. +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +enable_language(CXX) + +if (NOT CMAKE_GENERATOR MATCHES "Ninja") + message(FATAL_ERROR + "This test requires a 'Ninja' generator to be used.") +endif () + +add_library(ninja-exports-public) +target_sources(ninja-exports-public + PRIVATE + sources/module-impl.cxx + sources/module-internal-part-impl.cxx + sources/module-part-impl.cxx + sources/module-use.cxx + PUBLIC + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/sources" + FILES + sources/module.cxx + sources/module-part.cxx + FILE_SET internal_partitions TYPE CXX_MODULES FILES + sources/module-internal-part.cxx) +target_compile_features(ninja-exports-public + PRIVATE + cxx_std_20) +set_property(TARGET ninja-exports-public + PROPERTY EXPORT_NAME "with-public") + +install(TARGETS ninja-exports-public + EXPORT exp + FILE_SET modules + DESTINATION "lib/cxx" + COMPONENT "modules" + FILE_SET internal_partitions + DESTINATION "lib/cxx/internals" + COMPONENT "modules-internal") + +add_library(ninja-exports-private) +target_sources(ninja-exports-private + PRIVATE + sources/module-impl.cxx + sources/module-internal-part-impl.cxx + sources/module-part-impl.cxx + sources/module-use.cxx + PRIVATE + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/sources" + FILES + sources/module.cxx + sources/module-part.cxx + FILE_SET internal_partitions TYPE CXX_MODULES FILES + sources/module-internal-part.cxx) +target_compile_features(ninja-exports-private + PRIVATE + cxx_std_20) +set_property(TARGET ninja-exports-private + PROPERTY EXPORT_NAME "with-private") + +install(TARGETS ninja-exports-private + EXPORT exp) + +# Test multiple build exports. +export(EXPORT exp + FILE "${CMAKE_BINARY_DIR}/lib/cmake/export1/export1-targets.cmake" + NAMESPACE export1:: + CXX_MODULES_DIRECTORY "cxx-modules") +export(EXPORT exp + FILE "${CMAKE_BINARY_DIR}/lib/cmake/export2/export2-targets.cmake" + CXX_MODULES_DIRECTORY "cxx-modules") + +# Test multiple install exports. +install(EXPORT exp + DESTINATION "lib/cmake/export1" + NAMESPACE export1:: + CXX_MODULES_DIRECTORY "cxx-modules") +install(EXPORT exp + DESTINATION "lib/cmake/export2" + CXX_MODULES_DIRECTORY "cxx-modules") diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake new file mode 100644 index 0000000..b9a1315 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-check.cmake @@ -0,0 +1,34 @@ +include("${CMAKE_CURRENT_LIST_DIR}/check-json.cmake") + +if (RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(have_file 0) + foreach (config IN ITEMS Release Debug RelWithDebInfo MinSizeRel) + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-public.dir/${config}/CXXDependInfo.json") + continue () + endif () + set(have_file 1) + + set(CMAKE_BUILD_TYPE "${config}") + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-public.dir/${config}/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-public.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-private.dir/${config}/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-private.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") + endforeach () + + if (NOT have_file) + list(APPEND RunCMake_TEST_FAILED + "No recognized build configurations found.") + endif () +else () + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-public.dir/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-public.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") + + file(READ "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/ninja-file-sets-private.dir/CXXDependInfo.json" actual_contents) + file(READ "${CMAKE_CURRENT_LIST_DIR}/expect/NinjaDependInfoFileSet-private.json" expect_contents) + check_json("${actual_contents}" "${expect_contents}") +endif () diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt new file mode 100644 index 0000000..ca430cc --- /dev/null +++ b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet-stderr.txt @@ -0,0 +1,11 @@ +CMake Warning \(dev\) at NinjaDependInfoFileSet.cmake:14 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake new file mode 100644 index 0000000..74e729e --- /dev/null +++ b/Tests/RunCMake/CXXModules/NinjaDependInfoFileSet.cmake @@ -0,0 +1,59 @@ +# Fake out that we have dyndep; we only need to generate, not actually build +# here. +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +enable_language(CXX) + +if (NOT CMAKE_GENERATOR MATCHES "Ninja") + message(FATAL_ERROR + "This test requires a 'Ninja' generator to be used.") +endif () + +add_library(ninja-file-sets-public) +target_sources(ninja-file-sets-public + PRIVATE + sources/module-impl.cxx + sources/module-internal-part-impl.cxx + sources/module-part-impl.cxx + sources/module-use.cxx + PUBLIC + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/sources" + FILES + sources/module.cxx + sources/module-part.cxx + FILE_SET internal_partitions TYPE CXX_MODULES FILES + sources/module-internal-part.cxx) +target_compile_features(ninja-file-sets-public + PRIVATE + cxx_std_20) + +install(TARGETS ninja-file-sets-public + FILE_SET modules + DESTINATION "lib/cxx" + COMPONENT "modules" + FILE_SET internal_partitions + DESTINATION "lib/cxx/internals" + COMPONENT "modules-internal") + +add_library(ninja-file-sets-private) +target_sources(ninja-file-sets-private + PRIVATE + sources/module-impl.cxx + sources/module-internal-part-impl.cxx + sources/module-part-impl.cxx + sources/module-use.cxx + PRIVATE + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}/sources" + FILES + sources/module.cxx + sources/module-part.cxx + FILE_SET internal_partitions TYPE CXX_MODULES FILES + sources/module-internal-part.cxx) +target_compile_features(ninja-file-sets-private + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/NoCXX-result.txt b/Tests/RunCMake/CXXModules/NoCXX-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/NoCXX-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX-stderr.txt new file mode 100644 index 0000000..aa7f406 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX-stderr.txt @@ -0,0 +1,20 @@ +CMake Warning \(dev\) at NoCXX.cmake:4 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error in CMakeLists.txt: + The "nocxx" target has C\+\+ module sources but the "CXX" language has not + been enabled + +( +CMake Error in CMakeLists.txt: +( The "nocxx" target has C\+\+ module sources but the "CXX" language has not + been enabled +| The "nocxx" target contains C\+\+ module sources which are not supported by + the generator +) +)* +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/Tests/RunCMake/CXXModules/NoCXX.cmake b/Tests/RunCMake/CXXModules/NoCXX.cmake new file mode 100644 index 0000000..3c46f9d --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX.cmake @@ -0,0 +1,9 @@ +enable_language(C) + +add_library(nocxx) +target_sources(nocxx + PRIVATE + sources/c-anchor.c + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) diff --git a/Tests/RunCMake/CXXModules/NoCXX20-result.txt b/Tests/RunCMake/CXXModules/NoCXX20-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX20-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/NoCXX20-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX20-stderr.txt new file mode 100644 index 0000000..95d73b1 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX20-stderr.txt @@ -0,0 +1,20 @@ +CMake Warning \(dev\) at NoCXX20.cmake:4 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error in CMakeLists.txt: + The "nocxx20" target has C\+\+ module sources but is not using at least + "cxx_std_20" + +( +CMake Error in CMakeLists.txt: +( The "nocxx20" target has C\+\+ module sources but is not using at least + "cxx_std_20" +| The "nocxx20" target contains C\+\+ module sources which are not supported by + the generator +) +)* +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/Tests/RunCMake/CXXModules/NoCXX20.cmake b/Tests/RunCMake/CXXModules/NoCXX20.cmake new file mode 100644 index 0000000..b7372e8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX20.cmake @@ -0,0 +1,11 @@ +enable_language(CXX) + +add_library(nocxx20) +target_sources(nocxx20 + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +set_target_properties(nocxx20 + PROPERTIES + CXX_STANDARD 17 + CXX_STANDARD_REQUIRED ON) diff --git a/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt new file mode 100644 index 0000000..5f90ec8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag-stderr.txt @@ -0,0 +1,20 @@ +CMake Warning \(dev\) at NoCXX20ModuleFlag.cmake:4 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error in CMakeLists.txt: + The "noexperimentalflag" target has C\+\+ module sources but its experimental + support has not been requested + +( +CMake Error in CMakeLists.txt: +( The "noexperimentalflag" target has C\+\+ module sources but its experimental + support has not been requested +| The "noexperimentalflag" target contains C\+\+ module sources which are not + supported by the generator +) +)* +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake new file mode 100644 index 0000000..5f896f9 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoCXX20ModuleFlag.cmake @@ -0,0 +1,10 @@ +enable_language(CXX) + +add_library(noexperimentalflag) +target_sources(noexperimentalflag + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(noexperimentalflag + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt b/Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoDyndepSupport-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt b/Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt new file mode 100644 index 0000000..52f781f --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoDyndepSupport-stderr.txt @@ -0,0 +1,30 @@ +CMake Warning \(dev\) at NoDyndepSupport.cmake:10 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +(CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error: + The Ninja generator does not support C\+\+20 modules using Ninja version + + .* + + due to lack of required features. Ninja 1.10 or higher is required. + +|CMake Error in CMakeLists.txt: + The "nodyndep" target contains C\+\+ module sources which are not supported + by the generator + +( +CMake Error in CMakeLists.txt: + The "nodyndep" target contains C\+\+ module sources which are not supported + by the generator + +)*) +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/Tests/RunCMake/CXXModules/NoDyndepSupport.cmake b/Tests/RunCMake/CXXModules/NoDyndepSupport.cmake new file mode 100644 index 0000000..0954400 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NoDyndepSupport.cmake @@ -0,0 +1,16 @@ +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +if (NOT CMAKE_CXX_STANDARD_DEFAULT) + set(CMAKE_CXX_STANDARD_DEFAULT "11") +endif () + +add_library(nodyndep) +target_sources(nodyndep + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/module.cxx) +target_compile_features(nodyndep + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt new file mode 100644 index 0000000..a93eb40 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits-stderr.txt @@ -0,0 +1,22 @@ +CMake Warning \(dev\) at NotCXXSourceModuleHeaderUnits.cmake:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error in CMakeLists.txt: + Target "not-cxx-source" contains the source + + .*/Tests/RunCMake/CXXModules/sources/c-anchor.c + + in a file set of type "CXX_MODULE_HEADER_UNITS" but the source is not + classified as a "CXX" source. + + +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake new file mode 100644 index 0000000..af4ddac --- /dev/null +++ b/Tests/RunCMake/CXXModules/NotCXXSourceModuleHeaderUnits.cmake @@ -0,0 +1,15 @@ +enable_language(C) +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(not-cxx-source) +target_sources(not-cxx-source + PRIVATE + sources/cxx-anchor.cxx + PUBLIC + FILE_SET fs TYPE CXX_MODULE_HEADER_UNITS FILES + sources/c-anchor.c) +target_compile_features(not-cxx-source + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/NotCXXSourceModules-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt b/Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt new file mode 100644 index 0000000..d341c1f --- /dev/null +++ b/Tests/RunCMake/CXXModules/NotCXXSourceModules-stderr.txt @@ -0,0 +1,17 @@ +CMake Warning \(dev\) at NotCXXSourceModules.cmake:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:6 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error in CMakeLists.txt: + Target "not-cxx-source" contains the source + + .*/Tests/RunCMake/CXXModules/sources/c-anchor.c + + in a file set of type "CXX_MODULES" but the source is not classified as a + "CXX" source. + + +CMake Generate step failed. Build files cannot be regenerated correctly. diff --git a/Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake b/Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake new file mode 100644 index 0000000..f7a6060 --- /dev/null +++ b/Tests/RunCMake/CXXModules/NotCXXSourceModules.cmake @@ -0,0 +1,13 @@ +enable_language(C) +enable_language(CXX) +set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) +set(CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE "") + +add_library(not-cxx-source) +target_sources(not-cxx-source + PUBLIC + FILE_SET fs TYPE CXX_MODULES FILES + sources/c-anchor.c) +target_compile_features(not-cxx-source + PRIVATE + cxx_std_20) diff --git a/Tests/RunCMake/CXXModules/RunCMakeTest.cmake b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake new file mode 100644 index 0000000..3f17c1f --- /dev/null +++ b/Tests/RunCMake/CXXModules/RunCMakeTest.cmake @@ -0,0 +1,170 @@ +include(RunCMake) + +# For `if (IN_LIST)` +cmake_policy(SET CMP0057 NEW) + +run_cmake(compiler_introspection) +include("${RunCMake_BINARY_DIR}/compiler_introspection-build/info.cmake") + +# Test negative cases where C++20 modules do not work. +run_cmake(NoCXX) +if ("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES) + # This test requires that the compiler be told to compile in an older-than-20 + # standard. If the compiler forces a standard to be used, skip it. + if (NOT forced_cxx_standard) + run_cmake(NoCXX20) + endif () + + # This test uses C++20, but another prerequisite is missing, so forced + # standards don't matter. + run_cmake(NoCXX20ModuleFlag) +endif () + +if (RunCMake_GENERATOR MATCHES "Ninja") + execute_process( + COMMAND "${CMAKE_MAKE_PROGRAM}" --version + RESULT_VARIABLE res + OUTPUT_VARIABLE ninja_version + ERROR_VARIABLE err + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE) + + if (res) + message(WARNING + "Failed to determine `ninja` version: ${err}") + set(ninja_version "0") + endif () +endif () + +# Test behavior when the generator does not support C++20 modules. +if (NOT RunCMake_GENERATOR MATCHES "Ninja" OR + ninja_version VERSION_LESS "1.10" OR + NOT "cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES) + if ("cxx_std_20" IN_LIST CMAKE_CXX_COMPILE_FEATURES) + run_cmake(NoDyndepSupport) + endif () + + # Bail; the remaining tests require the generator to successfully generate + # with C++20 modules in the source list. + return () +endif () + +set(fileset_types + Modules + ModuleHeaderUnits) +set(scopes + Interface + Private + Public) +foreach (fileset_type IN LISTS fileset_types) + foreach (scope IN LISTS scopes) + run_cmake("FileSet${fileset_type}${scope}") + endforeach () + run_cmake("FileSet${fileset_type}InterfaceImported") + + # Test the error message when a non-C++ source file is found in the source + # list. + run_cmake("NotCXXSource${fileset_type}") +endforeach () + +run_cmake(InstallBMI) +run_cmake(InstallBMIGenericArgs) +run_cmake(InstallBMIIgnore) + +run_cmake(ExportBuildCxxModules) +run_cmake(ExportInstallCxxModules) + +# Generator-specific tests. +if (RunCMake_GENERATOR MATCHES "Ninja") + run_cmake(NinjaDependInfoFileSet) + run_cmake(NinjaDependInfoExport) + run_cmake(NinjaDependInfoBMIInstall) +else () + message(FATAL_ERROR + "Please add 'DependInfo' tests for the '${RunCMake_GENERATOR}' generator.") +endif () + +# Actual compilation tests. +if (NOT CMake_TEST_MODULE_COMPILATION) + return () +endif () + +function (run_cxx_module_test directory) + set(test_name "${directory}") + if (NOT ARGN STREQUAL "") + list(POP_FRONT ARGN test_name) + endif () + + set(RunCMake_TEST_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/examples/${directory}") + set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/examples/${test_name}-build") + + if (RunCMake_GENERATOR_IS_MULTI_CONFIG) + set(RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=Debug) + else () + set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug) + endif () + + if (RunCMake_CXXModules_INSTALL) + set(prefix "${RunCMake_BINARY_DIR}/examples/${test_name}-install") + file(REMOVE_RECURSE "${prefix}") + list(APPEND RunCMake_TEST_OPTIONS + "-DCMAKE_INSTALL_PREFIX=${prefix}") + endif () + + list(APPEND RunCMake_TEST_OPTIONS + "-DCMake_TEST_MODULE_COMPILATION_RULES=${CMake_TEST_MODULE_COMPILATION_RULES}" + ${ARGN}) + run_cmake("examples/${test_name}") + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command("examples/${test_name}-build" "${CMAKE_COMMAND}" --build . --config Debug) + if (RunCMake_CXXModules_INSTALL) + run_cmake_command("examples/${test_name}-install" "${CMAKE_COMMAND}" --build . --target install --config Debug) + endif () + run_cmake_command("examples/${test_name}-test" "${CMAKE_CTEST_COMMAND}" -C Debug --output-on-failure) +endfunction () + +string(REPLACE "," ";" CMake_TEST_MODULE_COMPILATION "${CMake_TEST_MODULE_COMPILATION}") + +# Tests which use named modules. +if ("named" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(simple) + run_cxx_module_test(library library-static -DBUILD_SHARED_LIBS=OFF) + run_cxx_module_test(generated) + run_cxx_module_test(public-req-private) + run_cxx_module_test(deep-chain) +endif () + +# Tests which use named modules in shared libraries. +if ("shared" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(library library-shared -DBUILD_SHARED_LIBS=ON) +endif () + +# Tests which use partitions. +if ("partitions" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(partitions) +endif () + +# Tests which use internal partitions. +if ("internal_partitions" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(internal-partitions) +endif () + +# Tests which install BMIs +if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(export-interface-build) + run_cxx_module_test(export-bmi-and-interface-build) +endif () + +# All of the following tests perform installation. +set(RunCMake_CXXModules_INSTALL 1) + +# Tests which install BMIs +if ("install_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(install-bmi) + run_cxx_module_test(install-bmi-and-interfaces) + + if ("export_bmi" IN_LIST CMake_TEST_MODULE_COMPILATION) + run_cxx_module_test(export-interface-install) + run_cxx_module_test(export-bmi-and-interface-install) + endif () +endif () diff --git a/Tests/RunCMake/CXXModules/check-json.cmake b/Tests/RunCMake/CXXModules/check-json.cmake new file mode 100644 index 0000000..19d0c8a --- /dev/null +++ b/Tests/RunCMake/CXXModules/check-json.cmake @@ -0,0 +1,160 @@ +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) + +function (json_placeholders in out) + string(REPLACE "<CONFIG>" "${CMAKE_BUILD_TYPE}" in "${in}") + if (RunCMake_GENERATOR_IS_MULTI_CONFIG) + string(REPLACE "<CONFIG_DIR>" "${CMAKE_BUILD_TYPE}/" in "${in}") + else () + string(REPLACE "<CONFIG_DIR>" "" in "${in}") + endif () + if (CMAKE_BUILD_TYPE) + string(REPLACE "<CONFIG_FORCE>" "${CMAKE_BUILD_TYPE}" in "${in}") + else () + string(REPLACE "<CONFIG_FORCE>" "noconfig" in "${in}") + endif () + string(REPLACE "<SOURCE_DIR>" "${RunCMake_SOURCE_DIR}" in "${in}") + string(REPLACE "<BINARY_DIR>" "${RunCMake_TEST_BINARY_DIR}" in "${in}") + set("${out}" "${in}" PARENT_SCOPE) +endfunction () + +function (check_json_value path actual_type expect_type actual_value expect_value) + if (NOT actual_type STREQUAL expect_type) + list(APPEND RunCMake_TEST_FAILED + "Type mismatch at ${path}: ${actual_type} vs. ${expect_type}") + return () + endif () + + if (actual_type STREQUAL NULL) + # Nothing to check + elseif (actual_type STREQUAL BOOLEAN) + if (NOT actual_value STREQUAL expect_value) + list(APPEND RunCMake_TEST_FAILED + "Boolean mismatch at ${path}: ${actual_value} vs. ${expect_value}") + endif () + elseif (actual_type STREQUAL NUMBER) + if (NOT actual_value EQUAL expect_value) + list(APPEND RunCMake_TEST_FAILED + "Number mismatch at ${path}: ${actual_value} vs. ${expect_value}") + endif () + elseif (actual_type STREQUAL STRING) + # Allow some values to be ignored. + if (expect_value STREQUAL "<IGNORE>") + return () + endif () + + json_placeholders("${expect_value}" expect_value_expanded) + if (NOT actual_value STREQUAL expect_value_expanded) + list(APPEND RunCMake_TEST_FAILED + "String mismatch at ${path}: ${actual_value} vs. ${expect_value_expanded}") + endif () + elseif (actual_type STREQUAL ARRAY) + check_json_array("${path}" "${actual_value}" "${expect_value}") + elseif (actual_type STREQUAL OBJECT) + check_json_object("${path}" "${actual_value}" "${expect_value}") + endif () +endfunction () + +# Check that two arrays are the same. +function (check_json_array path actual expect) + string(JSON actual_len LENGTH "${actual}") + string(JSON expect_len LENGTH "${expect}") + + set(iter_len "${actual_len}") + if (actual_len LESS expect_len) + list(APPEND RunCMake_TEST_FAILED + "Missing array items at ${path}") + elseif (expect_len LESS actual_len) + list(APPEND RunCMake_TEST_FAILED + "Extra array items at ${path}") + set(iter_len "${expect_len}") + endif () + + foreach (idx RANGE "${iter_len}") + if (idx EQUAL iter_len) + break () + endif () + + set(new_path "${path}[${idx}]") + string(JSON actual_type TYPE "${actual}" "${idx}") + string(JSON expect_type TYPE "${expect}" "${idx}") + string(JSON actual_value GET "${actual}" "${idx}") + string(JSON expect_value GET "${expect}" "${idx}") + check_json_value("${new_path}" "${actual_type}" "${expect_type}" "${actual_value}" "${expect_value}") + endforeach () +endfunction () + +# Check that two inner objects are the same. +function (check_json_object path actual expect) + string(JSON actual_len LENGTH "${actual}") + string(JSON expect_len LENGTH "${expect}") + + set(actual_keys "") + set(expect_keys "") + foreach (idx RANGE "${actual_len}") + if (idx EQUAL actual_len) + break () + endif () + + string(JSON actual_key MEMBER "${actual}" "${idx}") + list(APPEND actual_keys "${actual_key}") + endforeach () + foreach (idx RANGE "${expect_len}") + if (idx EQUAL expect_len) + break () + endif () + + string(JSON expect_key MEMBER "${expect}" "${idx}") + list(APPEND expect_keys "${expect_key}") + endforeach () + + json_placeholders("${expect_keys}" expect_keys_expanded) + + set(actual_keys_missed "${actual_keys}") + set(expect_keys_missed "${expect_keys}") + + set(common_keys "") + set(expect_keys_stack "${expect_keys}") + while (expect_keys_stack) + list(POP_BACK expect_keys_stack expect_key) + json_placeholders("${expect_key}" expect_key_expanded) + + if (expect_key_expanded IN_LIST actual_keys_missed AND + expect_key IN_LIST expect_keys_missed) + list(APPEND common_keys "${expect_key}") + endif () + + list(REMOVE_ITEM actual_keys_missed "${expect_key_expanded}") + list(REMOVE_ITEM expect_keys_missed "${expect_key}") + endwhile () + + if (actual_keys_missed) + string(REPLACE ";" ", " actual_keys_missed_text "${actual_keys_missed}") + list(APPEND RunCMake_TEST_FAILED + "Missing expected members at ${path}: ${actual_keys_missed_text}") + endif () + if (expect_keys_missed) + string(REPLACE ";" ", " expect_keys_missed_text "${expect_keys_missed}") + list(APPEND RunCMake_TEST_FAILED + "Extra unexpected members at ${path}: ${expect_keys_missed_text}") + endif () + + foreach (key IN LISTS common_keys) + json_placeholders("${key}" key_expanded) + set(new_path "${path}.${key_expanded}") + string(JSON actual_type TYPE "${actual}" "${key_expanded}") + string(JSON expect_type TYPE "${expect}" "${key}") + string(JSON actual_value GET "${actual}" "${key_expanded}") + string(JSON expect_value GET "${expect}" "${key}") + check_json_value("${new_path}" "${actual_type}" "${expect_type}" "${actual_value}" "${expect_value}") + endforeach () +endfunction () + +# Check that two JSON objects are the same. +function (check_json actual expect) + check_json_object("" "${actual}" "${expect}") +endfunction () + +string(REPLACE ";" "; " RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}") + +cmake_policy(POP) diff --git a/Tests/RunCMake/CXXModules/compiler_introspection.cmake b/Tests/RunCMake/CXXModules/compiler_introspection.cmake new file mode 100644 index 0000000..7a2df3d --- /dev/null +++ b/Tests/RunCMake/CXXModules/compiler_introspection.cmake @@ -0,0 +1,25 @@ +enable_language(CXX) + +set(info "") + +# See `Modules/Compiler/MSVC-CXX.cmake` for this. If there is explicitly no +# default, the feature list is populated to be everything. +if (DEFINED CMAKE_CXX_STANDARD_DEFAULT AND + CMAKE_CXX_STANDARD_DEFAULT STREQUAL "") + set(CMAKE_CXX_COMPILE_FEATURES "") +endif () + +# Detect if the environment forces a C++ standard, let the test selection know. +set(forced_cxx_standard 0) +if (CMAKE_CXX_FLAGS MATCHES "-std=") + set(forced_cxx_standard 1) +endif () + +# Forward information about the C++ compile features. +string(APPEND info "\ +set(CMAKE_CXX_COMPILE_FEATURES \"${CMAKE_CXX_COMPILE_FEATURES}\") +set(CMAKE_MAKE_PROGRAM \"${CMAKE_MAKE_PROGRAM}\") +set(forced_cxx_standard \"${forced_cxx_standard}\") +") + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/info.cmake" "${info}") diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake new file mode 100644 index 0000000..f99455b --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi-and-interfaces.cmake @@ -0,0 +1,22 @@ +function (check_for_bmi prefix destination name) + set(found 0) + foreach (ext IN ITEMS gcm) + if (EXISTS "${prefix}/${destination}/${name}.${ext}") + set(found 1) + break () + endif () + endforeach () + + if (NOT found) + message(SEND_ERROR + "Failed to find the ${name} BMI") + endif () +endfunction () + +function (check_for_interface prefix destination subdir name) + set(found 0) + if (NOT EXISTS "${prefix}/${destination}/${subdir}/${name}") + message(SEND_ERROR + "Failed to find the ${name} module interface") + endif () +endfunction () diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake new file mode 100644 index 0000000..91f3995 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-find-bmi.cmake @@ -0,0 +1,27 @@ +function (check_for_bmi prefix destination name) + set(found 0) + foreach (ext IN ITEMS gcm ifc) + if (EXISTS "${prefix}/${destination}/${name}.${ext}") + set(found 1) + break () + endif () + endforeach () + + if (NOT found) + message(SEND_ERROR + "Failed to find the ${name} BMI") + endif () +endfunction () + +function (check_for_interface prefix destination subdir name) + set(found 0) + if (NOT EXISTS "${prefix}/${destination}/${subdir}/${name}") + message(SEND_ERROR + "Failed to find the ${name} module interface") + endif () +endfunction () + +function (report_dirs prefix destination) + message("prefix: ${prefix}") + message("destination: ${destination}") +endfunction () diff --git a/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake b/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake new file mode 100644 index 0000000..381094e --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/cxx-modules-rules.cmake @@ -0,0 +1,18 @@ +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046") + +if (NOT EXISTS "${CMake_TEST_MODULE_COMPILATION_RULES}") + message(FATAL_ERROR + "The `CMake_TEST_MODULE_COMPILATION_RULES` file must be specified " + "for these tests to operate.") +endif () + +include("${CMake_TEST_MODULE_COMPILATION_RULES}") + +if (NOT CMake_TEST_CXXModules_UUID STREQUAL "a246741c-d067-4019-a8fb-3d16b0c9d1d3") + message(FATAL_ERROR + "The compilation rule file needs updated for changes in the test " + "suite. Please see the history for what needs to be updated.") +endif () + +include(CTest) +enable_testing() diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain-stderr.txt b/Tests/RunCMake/CXXModules/examples/deep-chain-stderr.txt new file mode 100644 index 0000000..5e4392a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/deep-chain-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/deep-chain/CMakeLists.txt new file mode 100644 index 0000000..515b240 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/deep-chain/CMakeLists.txt @@ -0,0 +1,66 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_deep_chain CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(a STATIC) +target_sources(a + PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + a.cxx) +target_compile_features(a PUBLIC cxx_std_20) + +add_library(b STATIC) +target_sources(b + PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + b.cxx) +target_compile_features(b PUBLIC cxx_std_20) +target_link_libraries(b PUBLIC a) + +add_library(c STATIC) +target_sources(c + PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + c.cxx) +target_compile_features(c PUBLIC cxx_std_20) +target_link_libraries(c PUBLIC b) + +add_library(d STATIC) +target_sources(d + PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + d.cxx) +target_compile_features(d PUBLIC cxx_std_20) +target_link_libraries(d PUBLIC c) + +add_library(e STATIC) +target_sources(e + PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + e.cxx) +target_compile_features(e PUBLIC cxx_std_20) +target_link_libraries(e PUBLIC d) + +add_executable(exe) +target_link_libraries(exe PRIVATE e) +target_sources(exe + PRIVATE + main.cxx) + +add_test(NAME exe COMMAND exe) diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/a.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/a.cxx new file mode 100644 index 0000000..9edaec9 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/deep-chain/a.cxx @@ -0,0 +1,6 @@ +export module a; + +export int a() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/b.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/b.cxx new file mode 100644 index 0000000..38ab0c2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/deep-chain/b.cxx @@ -0,0 +1,7 @@ +export module b; +import a; + +export int b() +{ + return a(); +} diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/c.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/c.cxx new file mode 100644 index 0000000..580a458 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/deep-chain/c.cxx @@ -0,0 +1,7 @@ +export module c; +import b; + +export int c() +{ + return b(); +} diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/d.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/d.cxx new file mode 100644 index 0000000..78bc5ba --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/deep-chain/d.cxx @@ -0,0 +1,7 @@ +export module d; +import c; + +export int d() +{ + return c(); +} diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/e.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/e.cxx new file mode 100644 index 0000000..e019440 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/deep-chain/e.cxx @@ -0,0 +1,7 @@ +export module e; +import d; + +export int e() +{ + return d(); +} diff --git a/Tests/RunCMake/CXXModules/examples/deep-chain/main.cxx b/Tests/RunCMake/CXXModules/examples/deep-chain/main.cxx new file mode 100644 index 0000000..0b7c15d --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/deep-chain/main.cxx @@ -0,0 +1,6 @@ +import e; + +int main(int argc, char* argv[]) +{ + return e(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt new file mode 100644 index 0000000..5e4392a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt new file mode 100644 index 0000000..a450b7e --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_export_bmi_and_interfaces CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(export_bmi_and_interfaces STATIC) +target_sources(export_bmi_and_interfaces + PRIVATE + forward.cxx + PRIVATE + FILE_SET modules_private TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + private.cxx + PUBLIC + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(export_bmi_and_interfaces PUBLIC cxx_std_20) + +install(TARGETS export_bmi_and_interfaces + EXPORT CXXModules + FILE_SET modules DESTINATION "lib/cxx/miu" + CXX_MODULES_BMI DESTINATION "lib/cxx/bmi") +export(EXPORT CXXModules + NAMESPACE CXXModules:: + FILE "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-targets.cmake" + CXX_MODULES_DIRECTORY "export_bmi_and_interfaces-cxx-modules") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_bmi_and_interfaces-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") + +set(generator + -G "${CMAKE_GENERATOR}") +if (CMAKE_GENERATOR_TOOLSET) + list(APPEND generator + -T "${CMAKE_GENERATOR_TOOLSET}") +endif () +if (CMAKE_GENERATOR_PLATFORM) + list(APPEND generator + -A "${CMAKE_GENERATOR_PLATFORM}") +endif () + +add_test(NAME export_bmi_and_interfaces_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_source_dir=${CMAKE_CURRENT_SOURCE_DIR}" + "-Dexpected_binary_dir=${CMAKE_CURRENT_BINARY_DIR}" + "-Dexport_bmi_and_interfaces_DIR=${CMAKE_CURRENT_BINARY_DIR}" + ${generator} + -S "${CMAKE_CURRENT_SOURCE_DIR}/test" + -B "${CMAKE_CURRENT_BINARY_DIR}/test") diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx new file mode 100644 index 0000000..7f53271 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/forward.cxx @@ -0,0 +1,6 @@ +import priv; + +int forwarding() +{ + return from_private(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx new file mode 100644 index 0000000..e0b1872 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/importable.cxx @@ -0,0 +1,8 @@ +export module importable; + +int forwarding(); + +export int from_import() +{ + return forwarding(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx new file mode 100644 index 0000000..c5b719a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/private.cxx @@ -0,0 +1,6 @@ +export module priv; + +export int from_private() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt new file mode 100644 index 0000000..b814b3b --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-build/test/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_library NONE) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046") + +find_package(export_bmi_and_interfaces REQUIRED) + +if (NOT TARGET CXXModules::export_bmi_and_interfaces) + message(FATAL_ERROR + "Missing imported target") +endif () + +get_property(file_sets TARGET CXXModules::export_bmi_and_interfaces + PROPERTY INTERFACE_CXX_MODULE_SETS) +if (NOT file_sets STREQUAL "modules") + message(FATAL_ERROR + "Incorrect exported file sets in `CXXModules::export_bmi_and_interfaces`: `${file_sets}`") +endif () + +get_property(file_set_files TARGET CXXModules::export_bmi_and_interfaces + PROPERTY CXX_MODULE_SET_modules) +if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx") + message(FATAL_ERROR + "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces`: `${file_set_files}`") +endif () + +get_property(imported_modules TARGET CXXModules::export_bmi_and_interfaces + PROPERTY IMPORTED_CXX_MODULES_DEBUG) +if (NOT imported_modules MATCHES "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/CMakeFiles/export_bmi_and_interfaces.dir(/Debug)?/importable.(gcm|pcm|ifc)") + message(FATAL_ERROR + "Incorrect exported modules in CXXModules::export_bmi_and_interfaces`: `${imported_modules}`") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt new file mode 100644 index 0000000..5e4392a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt new file mode 100644 index 0000000..a5574fe --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/CMakeLists.txt @@ -0,0 +1,59 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_export_bmi_and_interfaces CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(export_bmi_and_interfaces STATIC) +target_sources(export_bmi_and_interfaces + PRIVATE + forward.cxx + PRIVATE + FILE_SET modules_private TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + private.cxx + PUBLIC + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(export_bmi_and_interfaces PUBLIC cxx_std_20) + +install(TARGETS export_bmi_and_interfaces + EXPORT CXXModules + FILE_SET modules DESTINATION "lib/cxx/miu" + CXX_MODULES_BMI DESTINATION "lib/cxx/bmi") +install(EXPORT CXXModules + NAMESPACE CXXModules:: + DESTINATION "lib/cmake/export_bmi_and_interfaces" + FILE "export_bmi_and_interfaces-targets.cmake" + CXX_MODULES_DIRECTORY "export_bmi_and_interfaces-cxx-modules") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_bmi_and_interfaces-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/export_bmi_and_interfaces-config.cmake" + DESTINATION "lib/cmake/export_bmi_and_interfaces") + +set(generator + -G "${CMAKE_GENERATOR}") +if (CMAKE_GENERATOR_TOOLSET) + list(APPEND generator + -T "${CMAKE_GENERATOR_TOOLSET}") +endif () +if (CMAKE_GENERATOR_PLATFORM) + list(APPEND generator + -A "${CMAKE_GENERATOR_PLATFORM}") +endif () + +add_test(NAME export_bmi_and_interfaces_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_source_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu" + "-Dexpected_binary_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/bmi" + "-Dexport_bmi_and_interfaces_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/export_bmi_and_interfaces" + ${generator} + -S "${CMAKE_CURRENT_SOURCE_DIR}/test" + -B "${CMAKE_CURRENT_BINARY_DIR}/test") diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx new file mode 100644 index 0000000..7f53271 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/forward.cxx @@ -0,0 +1,6 @@ +import priv; + +int forwarding() +{ + return from_private(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx new file mode 100644 index 0000000..e0b1872 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/importable.cxx @@ -0,0 +1,8 @@ +export module importable; + +int forwarding(); + +export int from_import() +{ + return forwarding(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx new file mode 100644 index 0000000..c5b719a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/private.cxx @@ -0,0 +1,6 @@ +export module priv; + +export int from_private() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt new file mode 100644 index 0000000..db0484d --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-bmi-and-interface-install/test/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_library NONE) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046") + +find_package(export_bmi_and_interfaces REQUIRED) + +if (NOT TARGET CXXModules::export_bmi_and_interfaces) + message(FATAL_ERROR + "Missing imported target") +endif () + +get_property(file_sets TARGET CXXModules::export_bmi_and_interfaces + PROPERTY INTERFACE_CXX_MODULE_SETS) +if (NOT file_sets STREQUAL "modules") + message(FATAL_ERROR + "Incorrect exported file sets in `CXXModules::export_bmi_and_interfaces`: `${file_sets}`") +endif () + +get_property(file_set_files TARGET CXXModules::export_bmi_and_interfaces + PROPERTY CXX_MODULE_SET_modules) +if (NOT file_set_files STREQUAL "${expected_source_dir}/importable.cxx") + message(FATAL_ERROR + "Incorrect exported file set paths in CXXModules::export_bmi_and_interfaces`: `${file_set_files}`") +endif () + +get_property(imported_modules TARGET CXXModules::export_bmi_and_interfaces + PROPERTY IMPORTED_CXX_MODULES_DEBUG) +if (NOT imported_modules MATCHES "importable=${expected_source_dir}/importable.cxx,${expected_binary_dir}/importable.(gcm|pcm|ifc)") + message(FATAL_ERROR + "Incorrect exported modules in CXXModules::export_bmi_and_interfaces`: `${imported_modules}`") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt new file mode 100644 index 0000000..5e4392a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-build-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt new file mode 100644 index 0000000..80ddaf8 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/CMakeLists.txt @@ -0,0 +1,53 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_export_interfaces CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(export_interfaces STATIC) +target_sources(export_interfaces + PRIVATE + forward.cxx + PRIVATE + FILE_SET modules_private TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + private.cxx + PUBLIC + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(export_interfaces PUBLIC cxx_std_20) + +install(TARGETS export_interfaces + EXPORT CXXModules + FILE_SET modules DESTINATION "lib/cxx/miu") +export(EXPORT CXXModules + NAMESPACE CXXModules:: + FILE "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-targets.cmake") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_interfaces-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") + +set(generator + -G "${CMAKE_GENERATOR}") +if (CMAKE_GENERATOR_TOOLSET) + list(APPEND generator + -T "${CMAKE_GENERATOR_TOOLSET}") +endif () +if (CMAKE_GENERATOR_PLATFORM) + list(APPEND generator + -A "${CMAKE_GENERATOR_PLATFORM}") +endif () + +add_test(NAME export_interfaces_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_dir=${CMAKE_CURRENT_SOURCE_DIR}" + "-Dexport_interfaces_DIR=${CMAKE_CURRENT_BINARY_DIR}" + ${generator} + -S "${CMAKE_CURRENT_SOURCE_DIR}/test" + -B "${CMAKE_CURRENT_BINARY_DIR}/test") diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx new file mode 100644 index 0000000..7f53271 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/forward.cxx @@ -0,0 +1,6 @@ +import priv; + +int forwarding() +{ + return from_private(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx new file mode 100644 index 0000000..e0b1872 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/importable.cxx @@ -0,0 +1,8 @@ +export module importable; + +int forwarding(); + +export int from_import() +{ + return forwarding(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx new file mode 100644 index 0000000..c5b719a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/private.cxx @@ -0,0 +1,6 @@ +export module priv; + +export int from_private() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt new file mode 100644 index 0000000..6145210 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-build/test/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_library NONE) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046") + +find_package(export_interfaces REQUIRED) + +if (NOT TARGET CXXModules::export_interfaces) + message(FATAL_ERROR + "Missing imported target") +endif () + +get_property(file_sets TARGET CXXModules::export_interfaces + PROPERTY INTERFACE_CXX_MODULE_SETS) +if (NOT file_sets STREQUAL "modules") + message(FATAL_ERROR + "Incorrect exported file sets in `CXXModules::export_interfaces`: `${file_sets}`") +endif () + +get_property(file_set_files TARGET CXXModules::export_interfaces + PROPERTY CXX_MODULE_SET_modules) +if (NOT file_set_files STREQUAL "${expected_dir}/importable.cxx") + message(FATAL_ERROR + "Incorrect exported file set paths in CXXModules::export_interfaces`: `${file_set_files}`") +endif () + +get_property(imported_modules_set TARGET CXXModules::export_interfaces + PROPERTY IMPORTED_CXX_MODULES_DEBUG SET) +if (imported_modules_set) + message(FATAL_ERROR + "Unexpected C++ modules specified.") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt new file mode 100644 index 0000000..5e4392a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-install-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt new file mode 100644 index 0000000..1dfb6da --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_export_interfaces CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(export_interfaces STATIC) +target_sources(export_interfaces + PRIVATE + forward.cxx + PRIVATE + FILE_SET modules_private TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + private.cxx + PUBLIC + FILE_SET modules TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(export_interfaces PUBLIC cxx_std_20) + +install(TARGETS export_interfaces + EXPORT CXXModules + FILE_SET modules DESTINATION "lib/cxx/miu") +install(EXPORT CXXModules + NAMESPACE CXXModules:: + DESTINATION "lib/cmake/export_interfaces" + FILE "export_interfaces-targets.cmake") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-config.cmake" + "include(\"\${CMAKE_CURRENT_LIST_DIR}/export_interfaces-targets.cmake\") +set(\${CMAKE_FIND_PACKAGE_NAME}_FOUND 1) +") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/export_interfaces-config.cmake" + DESTINATION "lib/cmake/export_interfaces") + +set(generator + -G "${CMAKE_GENERATOR}") +if (CMAKE_GENERATOR_TOOLSET) + list(APPEND generator + -T "${CMAKE_GENERATOR_TOOLSET}") +endif () +if (CMAKE_GENERATOR_PLATFORM) + list(APPEND generator + -A "${CMAKE_GENERATOR_PLATFORM}") +endif () + +add_test(NAME export_interfaces_build + COMMAND + "${CMAKE_COMMAND}" + "-Dexpected_dir=${CMAKE_INSTALL_PREFIX}/lib/cxx/miu" + "-Dexport_interfaces_DIR=${CMAKE_INSTALL_PREFIX}/lib/cmake/export_interfaces" + ${generator} + -S "${CMAKE_CURRENT_SOURCE_DIR}/test" + -B "${CMAKE_CURRENT_BINARY_DIR}/test") diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx new file mode 100644 index 0000000..7f53271 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/forward.cxx @@ -0,0 +1,6 @@ +import priv; + +int forwarding() +{ + return from_private(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx new file mode 100644 index 0000000..e0b1872 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/importable.cxx @@ -0,0 +1,8 @@ +export module importable; + +int forwarding(); + +export int from_import() +{ + return forwarding(); +} diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx b/Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx new file mode 100644 index 0000000..c5b719a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/private.cxx @@ -0,0 +1,6 @@ +export module priv; + +export int from_private() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt new file mode 100644 index 0000000..6145210 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/export-interface-install/test/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_library NONE) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046") + +find_package(export_interfaces REQUIRED) + +if (NOT TARGET CXXModules::export_interfaces) + message(FATAL_ERROR + "Missing imported target") +endif () + +get_property(file_sets TARGET CXXModules::export_interfaces + PROPERTY INTERFACE_CXX_MODULE_SETS) +if (NOT file_sets STREQUAL "modules") + message(FATAL_ERROR + "Incorrect exported file sets in `CXXModules::export_interfaces`: `${file_sets}`") +endif () + +get_property(file_set_files TARGET CXXModules::export_interfaces + PROPERTY CXX_MODULE_SET_modules) +if (NOT file_set_files STREQUAL "${expected_dir}/importable.cxx") + message(FATAL_ERROR + "Incorrect exported file set paths in CXXModules::export_interfaces`: `${file_set_files}`") +endif () + +get_property(imported_modules_set TARGET CXXModules::export_interfaces + PROPERTY IMPORTED_CXX_MODULES_DEBUG SET) +if (imported_modules_set) + message(FATAL_ERROR + "Unexpected C++ modules specified.") +endif () diff --git a/Tests/RunCMake/CXXModules/examples/generated-stderr.txt b/Tests/RunCMake/CXXModules/examples/generated-stderr.txt new file mode 100644 index 0000000..b9bbf34 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/generated-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:12 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt new file mode 100644 index 0000000..73f7ff7 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/generated/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_generated CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/importable.cxx.in" + "${CMAKE_CURRENT_BINARY_DIR}/importable.cxx" + COPYONLY) + +add_executable(generated) +target_sources(generated + PRIVATE + main.cxx + PRIVATE + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_BINARY_DIR}" + FILES + "${CMAKE_CURRENT_BINARY_DIR}/importable.cxx") +target_compile_features(generated PUBLIC cxx_std_20) + +add_test(NAME generated COMMAND generated) diff --git a/Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in b/Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in new file mode 100644 index 0000000..a9287d7 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/generated/importable.cxx.in @@ -0,0 +1,5 @@ +export module importable; + +export int from_import() { + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/generated/main.cxx b/Tests/RunCMake/CXXModules/examples/generated/main.cxx new file mode 100644 index 0000000..feb38d2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/generated/main.cxx @@ -0,0 +1,6 @@ +import importable; + +int main(int argc, char* argv[]) +{ + return from_import(); +} diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt new file mode 100644 index 0000000..5e4392a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt new file mode 100644 index 0000000..efaca0e --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_install_bmi_and_interfaces CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(install_bmi_and_interfaces STATIC) +target_sources(install_bmi_and_interfaces + PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(install_bmi_and_interfaces PUBLIC cxx_std_20) + +install(TARGETS install_bmi_and_interfaces + ARCHIVE DESTINATION "lib" + CXX_MODULES_BMI DESTINATION "lib/cxx/bmi" + FILE_SET CXX_MODULES DESTINATION "lib/cxx/miu") + +add_test(NAME check-for-bmi + COMMAND + "${CMAKE_COMMAND}" + "-Dprefix=${CMAKE_INSTALL_PREFIX}" + "-Dbmi_destination=lib/cxx/bmi" + "-Dfs_destination=lib/cxx/miu" + -P "${CMAKE_CURRENT_SOURCE_DIR}/check-for-bmi.cmake") diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake new file mode 100644 index 0000000..a8ff1ad --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/check-for-bmi.cmake @@ -0,0 +1,7 @@ +include("${CMAKE_CURRENT_LIST_DIR}/../cxx-modules-find-bmi.cmake") + +report_dirs("${prefix}" "${bmi_destination}") +check_for_bmi("${prefix}" "${bmi_destination}" importable) + +report_dirs("${prefix}" "${fs_destination}") +check_for_interface("${prefix}" "${fs_destination}" "" importable.cxx) diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx new file mode 100644 index 0000000..607680a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/install-bmi-and-interfaces/importable.cxx @@ -0,0 +1,6 @@ +export module importable; + +export int from_import() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt b/Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt new file mode 100644 index 0000000..5e4392a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/install-bmi-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt new file mode 100644 index 0000000..4e039f9 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/install-bmi/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_install_bmi CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(install_bmi STATIC) +target_sources(install_bmi + PUBLIC + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(install_bmi PUBLIC cxx_std_20) + +install(TARGETS install_bmi + ARCHIVE DESTINATION "lib" + CXX_MODULES_BMI DESTINATION "lib/cxx/bmi") + +add_test(NAME check-for-bmi + COMMAND + "${CMAKE_COMMAND}" + "-Dprefix=${CMAKE_INSTALL_PREFIX}" + "-Ddestination=lib/cxx/bmi" + -P "${CMAKE_CURRENT_SOURCE_DIR}/check-for-bmi.cmake") diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake b/Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake new file mode 100644 index 0000000..ff84ed6 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/install-bmi/check-for-bmi.cmake @@ -0,0 +1,4 @@ +include("${CMAKE_CURRENT_LIST_DIR}/../cxx-modules-find-bmi.cmake") + +report_dirs("${prefix}" "${destination}") +check_for_bmi("${prefix}" "${destination}" importable) diff --git a/Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx b/Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx new file mode 100644 index 0000000..607680a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/install-bmi/importable.cxx @@ -0,0 +1,6 @@ +export module importable; + +export int from_import() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt b/Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt new file mode 100644 index 0000000..4652aec --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/internal-partitions-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt new file mode 100644 index 0000000..f5e9d94 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_internal_partitions CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +include(GenerateExportHeader) + +add_library(internal-partitions) +generate_export_header(internal-partitions) +target_sources(internal-partitions + PUBLIC + FILE_SET HEADERS + BASE_DIRS + "${CMAKE_CURRENT_BINARY_DIR}" + FILES + "${CMAKE_CURRENT_BINARY_DIR}/internal-partitions_export.h" + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx + partition.cxx) +target_compile_features(internal-partitions PUBLIC cxx_std_20) + +add_executable(exe) +target_link_libraries(exe PRIVATE internal-partitions) +target_sources(exe + PRIVATE + main.cxx) + +add_test(NAME exe COMMAND exe) diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx b/Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx new file mode 100644 index 0000000..b872ae9 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/importable.cxx @@ -0,0 +1,9 @@ +export module importable; +import : internal_partition; + +#include "internal-partitions_export.h" + +export INTERNAL_PARTITIONS_EXPORT int from_import() +{ + return from_partition(); +} diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx b/Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx new file mode 100644 index 0000000..feb38d2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/main.cxx @@ -0,0 +1,6 @@ +import importable; + +int main(int argc, char* argv[]) +{ + return from_import(); +} diff --git a/Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx b/Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx new file mode 100644 index 0000000..b15f53c --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/internal-partitions/partition.cxx @@ -0,0 +1,6 @@ +module importable : internal_partition; + +int from_partition() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt b/Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt new file mode 100644 index 0000000..4652aec --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/library-shared-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/library-static-stderr.txt b/Tests/RunCMake/CXXModules/examples/library-static-stderr.txt new file mode 100644 index 0000000..4652aec --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/library-static-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt new file mode 100644 index 0000000..27fd94f --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/library/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_library CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +include(GenerateExportHeader) + +add_library(library) +generate_export_header(library) +target_sources(library + PUBLIC + FILE_SET HEADERS + BASE_DIRS + "${CMAKE_CURRENT_BINARY_DIR}" + FILES + "${CMAKE_CURRENT_BINARY_DIR}/library_export.h" + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(library PUBLIC cxx_std_20) + +add_executable(exe) +target_link_libraries(exe PRIVATE library) +target_sources(exe + PRIVATE + main.cxx) + +add_test(NAME exe COMMAND exe) diff --git a/Tests/RunCMake/CXXModules/examples/library/importable.cxx b/Tests/RunCMake/CXXModules/examples/library/importable.cxx new file mode 100644 index 0000000..72ed0df --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/library/importable.cxx @@ -0,0 +1,8 @@ +export module importable; + +#include "library_export.h" + +export LIBRARY_EXPORT int from_import() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/library/main.cxx b/Tests/RunCMake/CXXModules/examples/library/main.cxx new file mode 100644 index 0000000..feb38d2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/library/main.cxx @@ -0,0 +1,6 @@ +import importable; + +int main(int argc, char* argv[]) +{ + return from_import(); +} diff --git a/Tests/RunCMake/CXXModules/examples/partitions-stderr.txt b/Tests/RunCMake/CXXModules/examples/partitions-stderr.txt new file mode 100644 index 0000000..4652aec --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/partitions-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:10 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt new file mode 100644 index 0000000..3a7b0d4 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/partitions/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_partitions CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +include(GenerateExportHeader) + +add_library(partitions) +generate_export_header(partitions) +target_sources(partitions + PUBLIC + FILE_SET HEADERS + BASE_DIRS + "${CMAKE_CURRENT_BINARY_DIR}" + FILES + "${CMAKE_CURRENT_BINARY_DIR}/partitions_export.h" + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx + partition.cxx) +target_compile_features(partitions PUBLIC cxx_std_20) + +add_executable(exe) +target_link_libraries(exe PRIVATE partitions) +target_sources(exe + PRIVATE + main.cxx) + +add_test(NAME exe COMMAND exe) diff --git a/Tests/RunCMake/CXXModules/examples/partitions/importable.cxx b/Tests/RunCMake/CXXModules/examples/partitions/importable.cxx new file mode 100644 index 0000000..d0ac2f4 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/partitions/importable.cxx @@ -0,0 +1,9 @@ +export module importable; +export import : partition; + +#include "partitions_export.h" + +export PARTITIONS_EXPORT int from_import() +{ + return from_partition(); +} diff --git a/Tests/RunCMake/CXXModules/examples/partitions/main.cxx b/Tests/RunCMake/CXXModules/examples/partitions/main.cxx new file mode 100644 index 0000000..c5b78c9 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/partitions/main.cxx @@ -0,0 +1,6 @@ +import importable; + +int main(int argc, char* argv[]) +{ + return from_import() + from_partition(); +} diff --git a/Tests/RunCMake/CXXModules/examples/partitions/partition.cxx b/Tests/RunCMake/CXXModules/examples/partitions/partition.cxx new file mode 100644 index 0000000..a47a4fd --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/partitions/partition.cxx @@ -0,0 +1,8 @@ +export module importable : partition; + +#include "partitions_export.h" + +export PARTITIONS_EXPORT int from_partition() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt b/Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/public-req-private-build-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt b/Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt new file mode 100644 index 0000000..b5f1c55 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/public-req-private-build-stdout.txt @@ -0,0 +1 @@ +CMake Error: Public C\+\+ module source `.*/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx` requires the `priv` C\+\+ module which is provided by a private source diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt b/Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt new file mode 100644 index 0000000..5e4392a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/public-req-private-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt new file mode 100644 index 0000000..600fec4 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/public-req-private/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_public_req_private CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_library(public_req_private) +target_sources(public_req_private + PRIVATE + FILE_SET private TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + priv.cxx + PUBLIC + FILE_SET public TYPE CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + pub.cxx) +target_compile_features(public_req_private PUBLIC cxx_std_20) + +add_test(NAME cmake-version COMMAND "${CMAKE_COMMAND}" --version) diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx b/Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx new file mode 100644 index 0000000..7c000b7 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/public-req-private/priv.cxx @@ -0,0 +1,6 @@ +export module priv; + +export int g() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx b/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx new file mode 100644 index 0000000..6ff2d23 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/public-req-private/pub.cxx @@ -0,0 +1,8 @@ +export module pub; + +import priv; + +export int f() +{ + return g(); +} diff --git a/Tests/RunCMake/CXXModules/examples/simple-stderr.txt b/Tests/RunCMake/CXXModules/examples/simple-stderr.txt new file mode 100644 index 0000000..5e4392a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/simple-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) at CMakeLists.txt:7 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Warning \(dev\): + C\+\+20 modules support via CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP is + experimental. It is meant only for compiler developers to try. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt b/Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt new file mode 100644 index 0000000..442e425 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/simple/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.24) +project(cxx_modules_simple CXX) + +include("${CMAKE_SOURCE_DIR}/../cxx-modules-rules.cmake") + +add_executable(simple) +target_sources(simple + PRIVATE + main.cxx + PRIVATE + FILE_SET CXX_MODULES + BASE_DIRS + "${CMAKE_CURRENT_SOURCE_DIR}" + FILES + importable.cxx) +target_compile_features(simple PUBLIC cxx_std_20) + +add_test(NAME simple COMMAND simple) diff --git a/Tests/RunCMake/CXXModules/examples/simple/importable.cxx b/Tests/RunCMake/CXXModules/examples/simple/importable.cxx new file mode 100644 index 0000000..607680a --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/simple/importable.cxx @@ -0,0 +1,6 @@ +export module importable; + +export int from_import() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/examples/simple/main.cxx b/Tests/RunCMake/CXXModules/examples/simple/main.cxx new file mode 100644 index 0000000..feb38d2 --- /dev/null +++ b/Tests/RunCMake/CXXModules/examples/simple/main.cxx @@ -0,0 +1,6 @@ +import importable; + +int main(int argc, char* argv[]) +{ + return from_import(); +} diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json new file mode 100644 index 0000000..65f0759 --- /dev/null +++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-private.json @@ -0,0 +1,45 @@ +{ + "bmi-installation": { + "destination": "lib/cxx/modules/private/<CONFIG>", + "message-level": "MESSAGE_LAZY", + "permissions": " OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ", + "script-location": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-private.dir/install-cxx-module-bmi-<CONFIG_FORCE>.cmake" + }, + "compiler-id": "<IGNORE>", + "config": "<CONFIG>", + "cxx-modules": { + "CMakeFiles/ninja-bmi-install-private.dir/sources/module-internal-part.cxx.o": { + "destination": null, + "name": "internal_partitions", + "relative-directory": "sources", + "source": "<SOURCE_DIR>/sources/module-internal-part.cxx", + "type": "CXX_MODULES", + "visibility": "PRIVATE" + }, + "CMakeFiles/ninja-bmi-install-private.dir/sources/module-part.cxx.o": { + "destination": null, + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module-part.cxx", + "type": "CXX_MODULES", + "visibility": "PRIVATE" + }, + "CMakeFiles/ninja-bmi-install-private.dir/sources/module.cxx.o": { + "destination": null, + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module.cxx", + "type": "CXX_MODULES", + "visibility": "PRIVATE" + } + }, + "dir-cur-bld": "<BINARY_DIR>", + "dir-cur-src": "<SOURCE_DIR>", + "dir-top-bld": "<BINARY_DIR>", + "dir-top-src": "<SOURCE_DIR>", + "exports": [], + "include-dirs": [], + "language": "CXX", + "linked-target-dirs": [], + "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-private.dir" +} diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json new file mode 100644 index 0000000..9c8a895 --- /dev/null +++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoBMIInstall-public.json @@ -0,0 +1,45 @@ +{ + "bmi-installation": { + "destination": "lib/cxx/modules/<CONFIG>", + "message-level": "", + "permissions": "", + "script-location": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-public.dir/install-cxx-module-bmi-noconfig.cmake" + }, + "compiler-id": "<IGNORE>", + "config": "<CONFIG>", + "cxx-modules": { + "CMakeFiles/ninja-bmi-install-public.dir/sources/module-internal-part.cxx.o": { + "destination": "lib/cxx/internals", + "name": "internal_partitions", + "relative-directory": "sources", + "source": "<SOURCE_DIR>/sources/module-internal-part.cxx", + "type": "CXX_MODULES", + "visibility": "PUBLIC" + }, + "CMakeFiles/ninja-bmi-install-public.dir/sources/module-part.cxx.o": { + "destination": "lib/cxx", + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module-part.cxx", + "type": "CXX_MODULES", + "visibility": "PUBLIC" + }, + "CMakeFiles/ninja-bmi-install-public.dir/sources/module.cxx.o": { + "destination": "lib/cxx", + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module.cxx", + "type": "CXX_MODULES", + "visibility": "PUBLIC" + } + }, + "dir-cur-bld": "<BINARY_DIR>", + "dir-cur-src": "<SOURCE_DIR>", + "dir-top-bld": "<BINARY_DIR>", + "dir-top-src": "<SOURCE_DIR>", + "exports": [], + "include-dirs": [], + "language": "CXX", + "linked-target-dirs": [], + "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-bmi-install-public.dir" +} diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json new file mode 100644 index 0000000..0545981 --- /dev/null +++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-private.json @@ -0,0 +1,73 @@ +{ + "bmi-installation": null, + "compiler-id": "<IGNORE>", + "config": "<CONFIG>", + "cxx-modules": { + "CMakeFiles/ninja-exports-private.dir/sources/module-internal-part.cxx.o": { + "destination": null, + "name": "internal_partitions", + "relative-directory": "sources", + "source": "<SOURCE_DIR>/sources/module-internal-part.cxx", + "type": "CXX_MODULES", + "visibility": "PRIVATE" + }, + "CMakeFiles/ninja-exports-private.dir/sources/module-part.cxx.o": { + "destination": null, + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module-part.cxx", + "type": "CXX_MODULES", + "visibility": "PRIVATE" + }, + "CMakeFiles/ninja-exports-private.dir/sources/module.cxx.o": { + "destination": null, + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module.cxx", + "type": "CXX_MODULES", + "visibility": "PRIVATE" + } + }, + "dir-cur-bld": "<BINARY_DIR>", + "dir-cur-src": "<SOURCE_DIR>", + "dir-top-bld": "<BINARY_DIR>", + "dir-top-src": "<SOURCE_DIR>", + "exports": [ + { + "cxx-module-info-dir" : "cxx-modules", + "destination" : "lib/cmake/export1", + "export-name" : "with-private", + "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/d2e2673818fd2bd8c45c0e3ed0e38fcd", + "install" : true, + "namespace" : "export1::" + }, + { + "cxx-module-info-dir" : "cxx-modules", + "destination" : "lib/cmake/export2", + "export-name" : "with-private", + "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/28cd47cb4c96ad5cadaa3fb1b0201ae8", + "install" : true, + "namespace" : "" + }, + { + "cxx-module-info-dir" : "cxx-modules", + "destination" : "<BINARY_DIR>/lib/cmake/export1", + "export-name" : "with-private", + "export-prefix" : "<BINARY_DIR>/lib/cmake/export1", + "install" : false, + "namespace" : "export1::" + }, + { + "cxx-module-info-dir" : "cxx-modules", + "destination" : "<BINARY_DIR>/lib/cmake/export2", + "export-name" : "with-private", + "export-prefix" : "<BINARY_DIR>/lib/cmake/export2", + "install" : false, + "namespace" : "" + } + ], + "include-dirs": [], + "language": "CXX", + "linked-target-dirs": [], + "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-private.dir" +} diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json new file mode 100644 index 0000000..adc3ae3 --- /dev/null +++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoExport-public.json @@ -0,0 +1,73 @@ +{ + "bmi-installation": null, + "compiler-id": "<IGNORE>", + "config": "<CONFIG>", + "cxx-modules": { + "CMakeFiles/ninja-exports-public.dir/sources/module-internal-part.cxx.o": { + "destination": "lib/cxx/internals", + "name": "internal_partitions", + "relative-directory": "sources", + "source": "<SOURCE_DIR>/sources/module-internal-part.cxx", + "type": "CXX_MODULES", + "visibility": "PUBLIC" + }, + "CMakeFiles/ninja-exports-public.dir/sources/module-part.cxx.o": { + "destination": "lib/cxx", + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module-part.cxx", + "type": "CXX_MODULES", + "visibility": "PUBLIC" + }, + "CMakeFiles/ninja-exports-public.dir/sources/module.cxx.o": { + "destination": "lib/cxx", + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module.cxx", + "type": "CXX_MODULES", + "visibility": "PUBLIC" + } + }, + "dir-cur-bld": "<BINARY_DIR>", + "dir-cur-src": "<SOURCE_DIR>", + "dir-top-bld": "<BINARY_DIR>", + "dir-top-src": "<SOURCE_DIR>", + "exports": [ + { + "cxx-module-info-dir" : "cxx-modules", + "destination" : "lib/cmake/export1", + "export-name" : "with-public", + "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/d2e2673818fd2bd8c45c0e3ed0e38fcd", + "install" : true, + "namespace" : "export1::" + }, + { + "cxx-module-info-dir" : "cxx-modules", + "destination" : "lib/cmake/export2", + "export-name" : "with-public", + "export-prefix" : "<BINARY_DIR>/CMakeFiles/Export/28cd47cb4c96ad5cadaa3fb1b0201ae8", + "install" : true, + "namespace" : "" + }, + { + "cxx-module-info-dir" : "cxx-modules", + "destination" : "<BINARY_DIR>/lib/cmake/export1", + "export-name" : "with-public", + "export-prefix" : "<BINARY_DIR>/lib/cmake/export1", + "install" : false, + "namespace" : "export1::" + }, + { + "cxx-module-info-dir" : "cxx-modules", + "destination" : "<BINARY_DIR>/lib/cmake/export2", + "export-name" : "with-public", + "export-prefix" : "<BINARY_DIR>/lib/cmake/export2", + "install" : false, + "namespace" : "" + } + ], + "include-dirs": [], + "language": "CXX", + "linked-target-dirs": [], + "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-exports-public.dir" +} diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json new file mode 100644 index 0000000..9ba6568 --- /dev/null +++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-private.json @@ -0,0 +1,40 @@ +{ + "bmi-installation": null, + "compiler-id": "<IGNORE>", + "config": "<CONFIG>", + "cxx-modules": { + "CMakeFiles/ninja-file-sets-private.dir/sources/module-internal-part.cxx.o": { + "destination": null, + "name": "internal_partitions", + "relative-directory": "sources", + "source": "<SOURCE_DIR>/sources/module-internal-part.cxx", + "type": "CXX_MODULES", + "visibility": "PRIVATE" + }, + "CMakeFiles/ninja-file-sets-private.dir/sources/module-part.cxx.o": { + "destination": null, + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module-part.cxx", + "type": "CXX_MODULES", + "visibility": "PRIVATE" + }, + "CMakeFiles/ninja-file-sets-private.dir/sources/module.cxx.o": { + "destination": null, + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module.cxx", + "type": "CXX_MODULES", + "visibility": "PRIVATE" + } + }, + "dir-cur-bld": "<BINARY_DIR>", + "dir-cur-src": "<SOURCE_DIR>", + "dir-top-bld": "<BINARY_DIR>", + "dir-top-src": "<SOURCE_DIR>", + "exports": [], + "include-dirs": [], + "language": "CXX", + "linked-target-dirs": [], + "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-private.dir" +} diff --git a/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json new file mode 100644 index 0000000..46e2cbf --- /dev/null +++ b/Tests/RunCMake/CXXModules/expect/NinjaDependInfoFileSet-public.json @@ -0,0 +1,40 @@ +{ + "bmi-installation": null, + "compiler-id": "<IGNORE>", + "config": "<CONFIG>", + "cxx-modules": { + "CMakeFiles/ninja-file-sets-public.dir/<CONFIG_DIR>sources/module-internal-part.cxx.o": { + "destination": "lib/cxx/internals", + "name": "internal_partitions", + "relative-directory": "sources", + "source": "<SOURCE_DIR>/sources/module-internal-part.cxx", + "type": "CXX_MODULES", + "visibility": "PUBLIC" + }, + "CMakeFiles/ninja-file-sets-public.dir/<CONFIG_DIR>sources/module-part.cxx.o": { + "destination": "lib/cxx", + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module-part.cxx", + "type": "CXX_MODULES", + "visibility": "PUBLIC" + }, + "CMakeFiles/ninja-file-sets-public.dir/<CONFIG_DIR>sources/module.cxx.o": { + "destination": "lib/cxx", + "name": "modules", + "relative-directory": "", + "source": "<SOURCE_DIR>/sources/module.cxx", + "type": "CXX_MODULES", + "visibility": "PUBLIC" + } + }, + "dir-cur-bld": "<BINARY_DIR>", + "dir-cur-src": "<SOURCE_DIR>", + "dir-top-bld": "<BINARY_DIR>", + "dir-top-src": "<SOURCE_DIR>", + "exports": [], + "include-dirs": [], + "language": "CXX", + "linked-target-dirs": [], + "module-dir": "<BINARY_DIR>/CMakeFiles/ninja-file-sets-public.dir" +} diff --git a/Tests/RunCMake/CXXModules/sources/c-anchor.c b/Tests/RunCMake/CXXModules/sources/c-anchor.c new file mode 100644 index 0000000..c782188 --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/c-anchor.c @@ -0,0 +1,4 @@ +int c_anchor() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx b/Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx new file mode 100644 index 0000000..9c94ec1 --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/cxx-anchor.cxx @@ -0,0 +1,4 @@ +int cxx_anchor() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/sources/module-header.h b/Tests/RunCMake/CXXModules/sources/module-header.h new file mode 100644 index 0000000..982617e --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/module-header.h @@ -0,0 +1,9 @@ +#ifndef module_header_h +#define module_header_h + +inline int h() +{ + return 0; +} + +#endif diff --git a/Tests/RunCMake/CXXModules/sources/module-impl.cxx b/Tests/RunCMake/CXXModules/sources/module-impl.cxx new file mode 100644 index 0000000..4718999 --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/module-impl.cxx @@ -0,0 +1,6 @@ +module M; + +int f() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx b/Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx new file mode 100644 index 0000000..be77b0d --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/module-internal-part-impl.cxx @@ -0,0 +1,11 @@ +#ifdef _MSC_VER +// Only MSVC supports this pattern. +module M : internal_part; +#else +module M; +#endif + +int i() +{ + return 0; +} diff --git a/Tests/RunCMake/CXXModules/sources/module-internal-part.cxx b/Tests/RunCMake/CXXModules/sources/module-internal-part.cxx new file mode 100644 index 0000000..fa82afb --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/module-internal-part.cxx @@ -0,0 +1,3 @@ +module M : internal_part; + +int i(); diff --git a/Tests/RunCMake/CXXModules/sources/module-part-impl.cxx b/Tests/RunCMake/CXXModules/sources/module-part-impl.cxx new file mode 100644 index 0000000..46d5d9f --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/module-part-impl.cxx @@ -0,0 +1,13 @@ +#ifdef _MSC_VER +// Only MSVC supports this pattern. +module M : part; +#else +module M; +#endif + +import M : internal_part; + +int p() +{ + return i(); +} diff --git a/Tests/RunCMake/CXXModules/sources/module-part.cxx b/Tests/RunCMake/CXXModules/sources/module-part.cxx new file mode 100644 index 0000000..137c16f --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/module-part.cxx @@ -0,0 +1,3 @@ +export module M : part; + +int p(); diff --git a/Tests/RunCMake/CXXModules/sources/module-use.cxx b/Tests/RunCMake/CXXModules/sources/module-use.cxx new file mode 100644 index 0000000..2d060cd --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/module-use.cxx @@ -0,0 +1,6 @@ +import M; + +int main(int argc, char* argv[]) +{ + return f() + p(); +} diff --git a/Tests/RunCMake/CXXModules/sources/module.cxx b/Tests/RunCMake/CXXModules/sources/module.cxx new file mode 100644 index 0000000..a631354 --- /dev/null +++ b/Tests/RunCMake/CXXModules/sources/module.cxx @@ -0,0 +1,5 @@ +export module M; +export import M : part; +import M : internal_part; + +int f(); diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCCompilerFlag.cmake index 276158c..bfb6f72 100644 --- a/Tests/RunCMake/CheckCompilerFlag/CheckCCompilerFlag.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCCompilerFlag.cmake @@ -1,33 +1,27 @@ enable_language (C) -include(CheckCompilerFlag) +include(CheckCCompilerFlag) set(C 1) # test that this is tolerated -# test that the check uses an isolated locale -set(_env_LC_ALL "${LC_ALL}") -set(ENV{LC_ALL} "BAD") - -check_compiler_flag(C "-_this_is_not_a_flag_" SHOULD_FAIL) -if(SHOULD_FAIL) - message(SEND_ERROR "invalid C compile flag didn't fail.") +if(NOT CMAKE_C_COMPILER_ID STREQUAL "PathScale") + set(DD --) endif() -if(CMAKE_C_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") - check_compiler_flag(C "-x c" SHOULD_WORK) - if(NOT SHOULD_WORK) - message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-x c' check failed") - endif() +check_c_compiler_flag("${DD}-_this_is_not_a_flag_" C_BOGUS_FLAG) +if(C_BOGUS_FLAG) + message(SEND_ERROR "CHECK_C_COMPILER_FLAG() succeeded, but should have failed") endif() - -if(CMAKE_C_COMPILER_ID STREQUAL "GNU") # LCC C compiler silently ignore -frtti instead of failing, so skip it here. - check_compiler_flag(C "-frtti" SHOULD_FAIL_RTTI) - if(SHOULD_FAIL_RTTI) - message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-frtti' check passed but should have failed") - endif() +unset(C_BOGUS_FLAG CACHE) +if(DEFINED C_BOGUS_FLAG) + # Verify that CHECK_C_COMPILER_FLAG didn't construct a normal variable + message(SEND_ERROR "CHECK_C_COMPILER_FLAG shouldn't construct C_BOGUS_FLAG as a normal variable") endif() -if(NOT "$ENV{LC_ALL}" STREQUAL "BAD") - message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag") +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "LCC") + unset(C_STRICT_PROTOTYPES CACHE) + CHECK_C_COMPILER_FLAG("-Werror;-Wstrict-prototypes" C_STRICT_PROTOTYPES) + if(NOT C_STRICT_PROTOTYPES) + message(SEND_ERROR "CHECK_C_COMPILER_FLAG failed -Werror -Wstrict-prototypes") + endif() endif() -set(ENV{LC_ALL} ${_env_LC_ALL}) diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCXXCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCXXCompilerFlag.cmake index dec31ec..eb20eb4 100644 --- a/Tests/RunCMake/CheckCompilerFlag/CheckCXXCompilerFlag.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCXXCompilerFlag.cmake @@ -1,26 +1,19 @@ enable_language (CXX) -include(CheckCompilerFlag) +include(CheckCXXCompilerFlag) set(CXX 1) # test that this is tolerated -# test that the check uses an isolated locale -set(_env_LC_ALL "${LC_ALL}") -set(ENV{LC_ALL} "BAD") - -check_compiler_flag(CXX "-_this_is_not_a_flag_" SHOULD_FAIL) -if(SHOULD_FAIL) - message(SEND_ERROR "invalid CXX compile flag didn't fail.") +if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "PathScale") + set(DD --) endif() -if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") - check_compiler_flag(CXX "-x c++" SHOULD_WORK) - if(NOT SHOULD_WORK) - message(SEND_ERROR "${CMAKE_CXX_COMPILER_ID} compiler flag '-x c++' check failed") - endif() +check_cxx_compiler_flag("${DD}-_this_is_not_a_flag_" CXX_BOGUS_FLAG) +if(CXX_BOGUS_FLAG) + message(SEND_ERROR "CHECK_CXX_COMPILER_FLAG() succeeded, but should have failed") endif() - -if(NOT "$ENV{LC_ALL}" STREQUAL "BAD") - message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag") +unset(CXX_BOGUS_FLAG CACHE) +if(DEFINED CXX_BOGUS_FLAG) + # Verify that CHECK_CXX_COMPILER_FLAG didn't construct a normal variable + message(SEND_ERROR "CHECK_CXX_COMPILER_FLAG shouldn't construct CXX_BOGUS_FLAG as a normal variable") endif() -set(ENV{LC_ALL} ${_env_LC_ALL}) diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake new file mode 100644 index 0000000..276158c --- /dev/null +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagC.cmake @@ -0,0 +1,33 @@ + +enable_language (C) +include(CheckCompilerFlag) + +set(C 1) # test that this is tolerated + +# test that the check uses an isolated locale +set(_env_LC_ALL "${LC_ALL}") +set(ENV{LC_ALL} "BAD") + +check_compiler_flag(C "-_this_is_not_a_flag_" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "invalid C compile flag didn't fail.") +endif() + +if(CMAKE_C_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC") + check_compiler_flag(C "-x c" SHOULD_WORK) + if(NOT SHOULD_WORK) + message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-x c' check failed") + endif() +endif() + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") # LCC C compiler silently ignore -frtti instead of failing, so skip it here. + check_compiler_flag(C "-frtti" SHOULD_FAIL_RTTI) + if(SHOULD_FAIL_RTTI) + message(SEND_ERROR "${CMAKE_C_COMPILER_ID} compiler flag '-frtti' check passed but should have failed") + endif() +endif() + +if(NOT "$ENV{LC_ALL}" STREQUAL "BAD") + message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag") +endif() +set(ENV{LC_ALL} ${_env_LC_ALL}) diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCUDACompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCUDA.cmake index 681a546..681a546 100644 --- a/Tests/RunCMake/CheckCompilerFlag/CheckCUDACompilerFlag.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCUDA.cmake diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake new file mode 100644 index 0000000..dec31ec --- /dev/null +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagCXX.cmake @@ -0,0 +1,26 @@ + +enable_language (CXX) +include(CheckCompilerFlag) + +set(CXX 1) # test that this is tolerated + +# test that the check uses an isolated locale +set(_env_LC_ALL "${LC_ALL}") +set(ENV{LC_ALL} "BAD") + +check_compiler_flag(CXX "-_this_is_not_a_flag_" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "invalid CXX compile flag didn't fail.") +endif() + +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|LCC|Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") + check_compiler_flag(CXX "-x c++" SHOULD_WORK) + if(NOT SHOULD_WORK) + message(SEND_ERROR "${CMAKE_CXX_COMPILER_ID} compiler flag '-x c++' check failed") + endif() +endif() + +if(NOT "$ENV{LC_ALL}" STREQUAL "BAD") + message(SEND_ERROR "ENV{LC_ALL} was not preserved by check_compiler_flag") +endif() +set(ENV{LC_ALL} ${_env_LC_ALL}) diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckFortranCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagFortran.cmake index 236f37b..236f37b 100644 --- a/Tests/RunCMake/CheckCompilerFlag/CheckFortranCompilerFlag.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagFortran.cmake diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagHIP.cmake index 339ce18..339ce18 100644 --- a/Tests/RunCMake/CheckCompilerFlag/CheckHIPCompilerFlag.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagHIP.cmake diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckISPCCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagISPC.cmake index 662319a..662319a 100644 --- a/Tests/RunCMake/CheckCompilerFlag/CheckISPCCompilerFlag.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagISPC.cmake diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckOBJCCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJC.cmake index f250f8d..f250f8d 100644 --- a/Tests/RunCMake/CheckCompilerFlag/CheckOBJCCompilerFlag.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJC.cmake diff --git a/Tests/RunCMake/CheckCompilerFlag/CheckOBJCXXCompilerFlag.cmake b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJCXX.cmake index bc940a6..bc940a6 100644 --- a/Tests/RunCMake/CheckCompilerFlag/CheckOBJCXXCompilerFlag.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/CheckCompilerFlagOBJCXX.cmake diff --git a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake index df2b667..b0e025c 100644 --- a/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckCompilerFlag/RunCMakeTest.cmake @@ -5,28 +5,30 @@ run_cmake(NonExistentLanguage) run_cmake(CheckCCompilerFlag) run_cmake(CheckCXXCompilerFlag) +run_cmake(CheckCompilerFlagC) +run_cmake(CheckCompilerFlagCXX) if (APPLE) - run_cmake(CheckOBJCCompilerFlag) - run_cmake(CheckOBJCXXCompilerFlag) + run_cmake(CheckCompilerFlagOBJC) + run_cmake(CheckCompilerFlagOBJCXX) endif() if (CMAKE_Fortran_COMPILER_ID) - run_cmake(CheckFortranCompilerFlag) + run_cmake(CheckCompilerFlagFortran) endif() if (CMake_TEST_CUDA) - run_cmake(CheckCUDACompilerFlag) + run_cmake(CheckCompilerFlagCUDA) endif() if(CMake_TEST_ISPC) - run_cmake(CheckISPCCompilerFlag) + run_cmake(CheckCompilerFlagISPC) endif() if(CMake_TEST_HIP) - run_cmake(CheckHIPCompilerFlag) + run_cmake(CheckCompilerFlagHIP) endif() if(APPLE) - run_cmake_with_options(HeaderpadWorkaround --debug-trycompile) + run_cmake(HeaderpadWorkaround) endif() diff --git a/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt b/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt index dc2c3ad..9a1ba04 100644 --- a/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt +++ b/Tests/RunCMake/CheckIPOSupported/default-lang-none-stderr.txt @@ -1,6 +1,6 @@ ^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\): - IPO is not supported \(no C/CXX/Fortran languages found in ENABLED_LANGUAGES - global property\)\. + IPO is not supported \(no C/CXX/CUDA/Fortran languages found in + ENABLED_LANGUAGES global property\)\. Call Stack \(most recent call first\): .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\) default-lang-none\.cmake:[0-9]+ \(check_ipo_supported\) diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckCLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagC.cmake index c8e87a4..c8e87a4 100644 --- a/Tests/RunCMake/CheckLinkerFlag/CheckCLinkerFlag.cmake +++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagC.cmake diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckCUDALinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCUDA.cmake index 84d6dd9..84d6dd9 100644 --- a/Tests/RunCMake/CheckLinkerFlag/CheckCUDALinkerFlag.cmake +++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCUDA.cmake diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckCXXLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCXX.cmake index 4e299b9..4e299b9 100644 --- a/Tests/RunCMake/CheckLinkerFlag/CheckCXXLinkerFlag.cmake +++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagCXX.cmake diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckFortranLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagFortran.cmake index bca288e..bca288e 100644 --- a/Tests/RunCMake/CheckLinkerFlag/CheckFortranLinkerFlag.cmake +++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagFortran.cmake diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagHIP.cmake index 3bf3b30..3bf3b30 100644 --- a/Tests/RunCMake/CheckLinkerFlag/CheckHIPLinkerFlag.cmake +++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagHIP.cmake diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckOBJCLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJC.cmake index fa1d18e..fa1d18e 100644 --- a/Tests/RunCMake/CheckLinkerFlag/CheckOBJCLinkerFlag.cmake +++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJC.cmake diff --git a/Tests/RunCMake/CheckLinkerFlag/CheckOBJCXXLinkerFlag.cmake b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJCXX.cmake index 414efb8..414efb8 100644 --- a/Tests/RunCMake/CheckLinkerFlag/CheckOBJCXXLinkerFlag.cmake +++ b/Tests/RunCMake/CheckLinkerFlag/CheckLinkerFlagOBJCXX.cmake diff --git a/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake b/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake index 39fc430..5915ba1 100644 --- a/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckLinkerFlag/RunCMakeTest.cmake @@ -1,22 +1,22 @@ include(RunCMake) if (CMAKE_C_COMPILER_ID MATCHES "Clang|GNU|LCC") - run_cmake(CheckCLinkerFlag) - run_cmake(CheckCXXLinkerFlag) + run_cmake(CheckLinkerFlagC) + run_cmake(CheckLinkerFlagCXX) if (APPLE) - run_cmake(CheckOBJCLinkerFlag) - run_cmake(CheckOBJCXXLinkerFlag) + run_cmake(CheckLinkerFlagOBJC) + run_cmake(CheckLinkerFlagOBJCXX) endif() endif() if (CMAKE_Fortran_COMPILER_ID MATCHES "GNU|LCC") - run_cmake(CheckFortranLinkerFlag) + run_cmake(CheckLinkerFlagFortran) endif() if (CMake_TEST_CUDA) - run_cmake(CheckCUDALinkerFlag) + run_cmake(CheckLinkerFlagCUDA) endif() if (CMake_TEST_HIP) - run_cmake(CheckHIPLinkerFlag) + run_cmake(CheckLinkerFlagHIP) endif() diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckCSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckCSourceCompiles.cmake index 4f73622..7104650 100644 --- a/Tests/RunCMake/CheckSourceCompiles/CheckCSourceCompiles.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/CheckCSourceCompiles.cmake @@ -1,15 +1,15 @@ enable_language (C) -include(CheckSourceCompiles) +include(CheckCSourceCompiles) set(C 1) # test that this is tolerated -check_source_compiles(C "I don't build" SHOULD_FAIL) +check_c_source_compiles("I don't build" SHOULD_FAIL) if(SHOULD_FAIL) message(SEND_ERROR "invalid C source didn't fail.") endif() -check_source_compiles(C "int main() {return 0;}" SHOULD_BUILD) +check_c_source_compiles("int main() {return 0;}" SHOULD_BUILD) if(NOT SHOULD_BUILD) message(SEND_ERROR "Test fail for valid C source.") endif() diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckCXXSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckCXXSourceCompiles.cmake index 97c9c30..7c9830a 100644 --- a/Tests/RunCMake/CheckSourceCompiles/CheckCXXSourceCompiles.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/CheckCXXSourceCompiles.cmake @@ -1,15 +1,15 @@ enable_language (CXX) -include(CheckSourceCompiles) +include(CheckCXXSourceCompiles) set(CXX 1) # test that this is tolerated -check_source_compiles(CXX "I don't build" SHOULD_FAIL) +check_cxx_source_compiles("I don't build" SHOULD_FAIL) if(SHOULD_FAIL) message(SEND_ERROR "invalid CXX source didn't fail.") endif() -check_source_compiles(CXX [=[ +check_cxx_source_compiles([=[ #include <vector> int main() { return 0; @@ -20,8 +20,8 @@ if(NOT SHOULD_BUILD) message(SEND_ERROR "Test fail for valid CXX source.") endif() -check_source_compiles(CXX "void l(char const (&x)[2]){}; int main() { l(\"\\n\"); return 0;}" - SHOULD_BUILD_COMPLEX) +CHECK_CXX_SOURCE_COMPILES("void l(char const (&x)[2]){}; int main() { l(\"\\\\n\"); return 0;}" + SHOULD_BUILD_COMPLEX) if(NOT SHOULD_BUILD_COMPLEX) message(SEND_ERROR "Test fail for valid CXX complex source.") diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckOBJCSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckOBJCSourceCompiles.cmake index 76a5009..ac43a1e 100644 --- a/Tests/RunCMake/CheckSourceCompiles/CheckOBJCSourceCompiles.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/CheckOBJCSourceCompiles.cmake @@ -1,9 +1,14 @@ enable_language (OBJC) -include(CheckSourceCompiles) +include(CheckOBJCSourceCompiles) set(OBJC 1) # test that this is tolerated -check_source_compiles(OBJC [[ +check_objc_source_compiles("I don't build in Objective-C" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "invalid OBJC source didn't fail.") +endif() + +check_objc_source_compiles([[ #import <Foundation/Foundation.h> int main() { NSObject *foo; diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckOBJCXXSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckOBJCXXSourceCompiles.cmake index 814237e..0088956 100644 --- a/Tests/RunCMake/CheckSourceCompiles/CheckOBJCXXSourceCompiles.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/CheckOBJCXXSourceCompiles.cmake @@ -1,9 +1,14 @@ enable_language (OBJCXX) -include(CheckSourceCompiles) +include(CheckOBJCXXSourceCompiles) set(OBJCXX 1) # test that this is tolerated -check_source_compiles(OBJCXX [[ +check_objcxx_source_compiles("I don't build in Objective-C++" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "invalid OBJCXX source didn't fail.") +endif() + +check_objcxx_source_compiles([[ #include <vector> #import <Foundation/Foundation.h> int main() { diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesC.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesC.cmake new file mode 100644 index 0000000..4f73622 --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesC.cmake @@ -0,0 +1,15 @@ + +enable_language (C) +include(CheckSourceCompiles) + +set(C 1) # test that this is tolerated + +check_source_compiles(C "I don't build" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "invalid C source didn't fail.") +endif() + +check_source_compiles(C "int main() {return 0;}" SHOULD_BUILD) +if(NOT SHOULD_BUILD) + message(SEND_ERROR "Test fail for valid C source.") +endif() diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckCUDASourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCUDA.cmake index 2190649..2190649 100644 --- a/Tests/RunCMake/CheckSourceCompiles/CheckCUDASourceCompiles.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCUDA.cmake diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCXX.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCXX.cmake new file mode 100644 index 0000000..97c9c30 --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesCXX.cmake @@ -0,0 +1,28 @@ + +enable_language (CXX) +include(CheckSourceCompiles) + +set(CXX 1) # test that this is tolerated + +check_source_compiles(CXX "I don't build" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "invalid CXX source didn't fail.") +endif() + +check_source_compiles(CXX [=[ + #include <vector> + int main() { + return 0; + } +]=] + SHOULD_BUILD) +if(NOT SHOULD_BUILD) + message(SEND_ERROR "Test fail for valid CXX source.") +endif() + +check_source_compiles(CXX "void l(char const (&x)[2]){}; int main() { l(\"\\n\"); return 0;}" + SHOULD_BUILD_COMPLEX) + +if(NOT SHOULD_BUILD_COMPLEX) + message(SEND_ERROR "Test fail for valid CXX complex source.") +endif() diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckFortranSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesFortran.cmake index 48dc525..48dc525 100644 --- a/Tests/RunCMake/CheckSourceCompiles/CheckFortranSourceCompiles.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesFortran.cmake diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesHIP.cmake index 911a0d7..911a0d7 100644 --- a/Tests/RunCMake/CheckSourceCompiles/CheckHIPSourceCompiles.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesHIP.cmake diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckISPCSourceCompiles.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesISPC.cmake index 74b83c0..74b83c0 100644 --- a/Tests/RunCMake/CheckSourceCompiles/CheckISPCSourceCompiles.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesISPC.cmake diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJC.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJC.cmake new file mode 100644 index 0000000..76a5009 --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJC.cmake @@ -0,0 +1,16 @@ +enable_language (OBJC) +include(CheckSourceCompiles) + +set(OBJC 1) # test that this is tolerated + +check_source_compiles(OBJC [[ + #import <Foundation/Foundation.h> + int main() { + NSObject *foo; + return 0; + } +]] SHOULD_BUILD) + +if(NOT SHOULD_BUILD) + message(SEND_ERROR "Test fail for valid OBJC source.") +endif() diff --git a/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJCXX.cmake b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJCXX.cmake new file mode 100644 index 0000000..814237e --- /dev/null +++ b/Tests/RunCMake/CheckSourceCompiles/CheckSourceCompilesOBJCXX.cmake @@ -0,0 +1,19 @@ +enable_language (OBJCXX) +include(CheckSourceCompiles) + +set(OBJCXX 1) # test that this is tolerated + +check_source_compiles(OBJCXX [[ + #include <vector> + #import <Foundation/Foundation.h> + int main() { + std::vector<int> v; + NSObject *foo; + return 0; + } +]] SHOULD_BUILD) + + +if(NOT SHOULD_BUILD) + message(SEND_ERROR "Test fail for OBJCXX source.") +endif() diff --git a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake index 530f133..df77d3d 100644 --- a/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckSourceCompiles/RunCMakeTest.cmake @@ -6,24 +6,28 @@ run_cmake(UnknownArgument) run_cmake(CheckCSourceCompiles) run_cmake(CheckCXXSourceCompiles) +run_cmake(CheckSourceCompilesC) +run_cmake(CheckSourceCompilesCXX) if (APPLE) run_cmake(CheckOBJCSourceCompiles) run_cmake(CheckOBJCXXSourceCompiles) + run_cmake(CheckSourceCompilesOBJC) + run_cmake(CheckSourceCompilesOBJCXX) endif() if (CMAKE_Fortran_COMPILER_ID) - run_cmake(CheckFortranSourceCompiles) + run_cmake(CheckSourceCompilesFortran) endif() if (CMake_TEST_CUDA) - run_cmake(CheckCUDASourceCompiles) + run_cmake(CheckSourceCompilesCUDA) endif() if(CMake_TEST_ISPC) - run_cmake(CheckISPCSourceCompiles) + run_cmake(CheckSourceCompilesISPC) endif() if(CMake_TEST_HIP) - run_cmake(CheckHIPSourceCompiles) + run_cmake(CheckSourceCompilesHIP) endif() diff --git a/Tests/RunCMake/CheckSourceRuns/CheckCSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckCSourceRuns.cmake index 96a1027..c0f9463 100644 --- a/Tests/RunCMake/CheckSourceRuns/CheckCSourceRuns.cmake +++ b/Tests/RunCMake/CheckSourceRuns/CheckCSourceRuns.cmake @@ -1,15 +1,15 @@ enable_language (C) -include(CheckSourceRuns) +include(CheckCSourceRuns) set(C 1) # test that this is tolerated -check_source_runs(C "int main() {return 2;}" SHOULD_FAIL) +check_c_source_runs("int main() {return 2;}" SHOULD_FAIL) if(SHOULD_FAIL) - message(SEND_ERROR "C check_source_runs succeeded, but should have failed.") + message(SEND_ERROR "check_c_source_runs succeeded, but should have failed.") endif() -check_source_runs(C "int main() {return 0;}" SHOULD_RUN) +check_c_source_runs("int main() {return 0;}" SHOULD_RUN) if(NOT SHOULD_RUN) - message(SEND_ERROR "C check_source_runs failed for valid C executable.") + message(SEND_ERROR "check_c_source_runs failed for valid C executable.") endif() diff --git a/Tests/RunCMake/CheckSourceRuns/CheckCXXSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckCXXSourceRuns.cmake index c4bef6e..c4c9026 100644 --- a/Tests/RunCMake/CheckSourceRuns/CheckCXXSourceRuns.cmake +++ b/Tests/RunCMake/CheckSourceRuns/CheckCXXSourceRuns.cmake @@ -1,15 +1,15 @@ enable_language (CXX) -include(CheckSourceRuns) +include(CheckCXXSourceRuns) set(CXX 1) # test that this is tolerated -check_source_runs(CXX "int main() {return 2;}" SHOULD_FAIL) +check_cxx_source_runs("int main() {return 2;}" SHOULD_FAIL) if(SHOULD_FAIL) - message(SEND_ERROR "CXX check_source_runs succeeded, but should have failed.") + message(SEND_ERROR "check_cxx_source_runs succeeded, but should have failed.") endif() -check_source_runs(CXX +check_cxx_source_runs( [=[ #include <vector> int main() { @@ -18,5 +18,5 @@ check_source_runs(CXX ]=] SHOULD_RUN) if(NOT SHOULD_RUN) - message(SEND_ERROR "CXX check_source_runs failed for valid C executable.") + message(SEND_ERROR "check_cxx_source_runs failed for valid C executable.") endif() diff --git a/Tests/RunCMake/CheckSourceRuns/CheckOBJCSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckOBJCSourceRuns.cmake index b828352..604b2a1 100644 --- a/Tests/RunCMake/CheckSourceRuns/CheckOBJCSourceRuns.cmake +++ b/Tests/RunCMake/CheckSourceRuns/CheckOBJCSourceRuns.cmake @@ -1,9 +1,14 @@ enable_language (OBJC) -include(CheckSourceRuns) +include(CheckOBJCSourceRuns) set(OBJC 1) # test that this is tolerated -check_source_runs(OBJC [[ +check_objc_source_runs("int main() {return 2;}" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "check_objc_source_runs succeeded, but should have failed.") +endif() + +check_objc_source_runs([[ #import <Foundation/Foundation.h> int main() { NSObject *foo; diff --git a/Tests/RunCMake/CheckSourceRuns/CheckOBJCXXSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckOBJCXXSourceRuns.cmake index 8a56f13..b220166 100644 --- a/Tests/RunCMake/CheckSourceRuns/CheckOBJCXXSourceRuns.cmake +++ b/Tests/RunCMake/CheckSourceRuns/CheckOBJCXXSourceRuns.cmake @@ -1,9 +1,14 @@ enable_language (OBJCXX) -include(CheckSourceRuns) +include(CheckOBJCXXSourceRuns) set(OBJCXX 1) # test that this is tolerated -check_source_runs(OBJCXX [[ +check_objcxx_source_runs("int main() {return 2;}" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "check_objcxx_source_runs succeeded, but should have failed.") +endif() + +check_objcxx_source_runs([[ #include <vector> #import <Foundation/Foundation.h> int main() { diff --git a/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsC.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsC.cmake new file mode 100644 index 0000000..96a1027 --- /dev/null +++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsC.cmake @@ -0,0 +1,15 @@ + +enable_language (C) +include(CheckSourceRuns) + +set(C 1) # test that this is tolerated + +check_source_runs(C "int main() {return 2;}" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "C check_source_runs succeeded, but should have failed.") +endif() + +check_source_runs(C "int main() {return 0;}" SHOULD_RUN) +if(NOT SHOULD_RUN) + message(SEND_ERROR "C check_source_runs failed for valid C executable.") +endif() diff --git a/Tests/RunCMake/CheckSourceRuns/CheckCUDASourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCUDA.cmake index ea5f4f9..ea5f4f9 100644 --- a/Tests/RunCMake/CheckSourceRuns/CheckCUDASourceRuns.cmake +++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCUDA.cmake diff --git a/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCXX.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCXX.cmake new file mode 100644 index 0000000..c4bef6e --- /dev/null +++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsCXX.cmake @@ -0,0 +1,22 @@ + +enable_language (CXX) +include(CheckSourceRuns) + +set(CXX 1) # test that this is tolerated + +check_source_runs(CXX "int main() {return 2;}" SHOULD_FAIL) +if(SHOULD_FAIL) + message(SEND_ERROR "CXX check_source_runs succeeded, but should have failed.") +endif() + +check_source_runs(CXX +[=[ + #include <vector> + int main() { + return 0; + } +]=] + SHOULD_RUN) +if(NOT SHOULD_RUN) + message(SEND_ERROR "CXX check_source_runs failed for valid C executable.") +endif() diff --git a/Tests/RunCMake/CheckSourceRuns/CheckFortranSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsFortran.cmake index 50e8ec8..50e8ec8 100644 --- a/Tests/RunCMake/CheckSourceRuns/CheckFortranSourceRuns.cmake +++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsFortran.cmake diff --git a/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsHIP.cmake index d9fb8c2..d9fb8c2 100644 --- a/Tests/RunCMake/CheckSourceRuns/CheckHIPSourceRuns.cmake +++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsHIP.cmake diff --git a/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJC.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJC.cmake new file mode 100644 index 0000000..b828352 --- /dev/null +++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJC.cmake @@ -0,0 +1,16 @@ +enable_language (OBJC) +include(CheckSourceRuns) + +set(OBJC 1) # test that this is tolerated + +check_source_runs(OBJC [[ + #import <Foundation/Foundation.h> + int main() { + NSObject *foo; + return 0; + } +]] SHOULD_BUILD) + +if(NOT SHOULD_BUILD) + message(SEND_ERROR "Test fail for valid OBJC source.") +endif() diff --git a/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJCXX.cmake b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJCXX.cmake new file mode 100644 index 0000000..8a56f13 --- /dev/null +++ b/Tests/RunCMake/CheckSourceRuns/CheckSourceRunsOBJCXX.cmake @@ -0,0 +1,19 @@ +enable_language (OBJCXX) +include(CheckSourceRuns) + +set(OBJCXX 1) # test that this is tolerated + +check_source_runs(OBJCXX [[ + #include <vector> + #import <Foundation/Foundation.h> + int main() { + std::vector<int> v; + NSObject *foo; + return 0; + } +]] SHOULD_BUILD) + + +if(NOT SHOULD_BUILD) + message(SEND_ERROR "Test fail for OBJCXX source.") +endif() diff --git a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake index 4784103..64cecfc 100644 --- a/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake +++ b/Tests/RunCMake/CheckSourceRuns/RunCMakeTest.cmake @@ -6,20 +6,24 @@ run_cmake(UnknownArgument) run_cmake(CheckCSourceRuns) run_cmake(CheckCXXSourceRuns) +run_cmake(CheckSourceRunsC) +run_cmake(CheckSourceRunsCXX) if (APPLE) run_cmake(CheckOBJCSourceRuns) run_cmake(CheckOBJCXXSourceRuns) + run_cmake(CheckSourceRunsOBJC) + run_cmake(CheckSourceRunsOBJCXX) endif() if (CMAKE_Fortran_COMPILER_ID) - run_cmake(CheckFortranSourceRuns) + run_cmake(CheckSourceRunsFortran) endif() if (CMake_TEST_CUDA) - run_cmake(CheckCUDASourceRuns) + run_cmake(CheckSourceRunsCUDA) endif() if (CMake_TEST_HIP) - run_cmake(CheckHIPSourceRuns) + run_cmake(CheckSourceRunsHIP) endif() diff --git a/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake b/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake index ee41d94..5e3fbc4 100644 --- a/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake +++ b/Tests/RunCMake/ClangTidy/RunCMakeTest.cmake @@ -29,3 +29,4 @@ if (NOT RunCMake_GENERATOR STREQUAL "Watcom WMake") endif() endif() run_tidy(C-bad) +run_tidy(compdb) diff --git a/Tests/RunCMake/ClangTidy/compdb.cmake b/Tests/RunCMake/ClangTidy/compdb.cmake new file mode 100644 index 0000000..f83e0ae --- /dev/null +++ b/Tests/RunCMake/ClangTidy/compdb.cmake @@ -0,0 +1,7 @@ +enable_language(C) + +# Include a --checks option to confirm that we don't match options that start +# with --, only a standalone -- +set(CMAKE_C_CLANG_TIDY "${PSEUDO_TIDY}" -p ${CMAKE_BINARY_DIR} --checks=*) + +add_executable(main main.c) diff --git a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt deleted file mode 100644 index 202ef80..0000000 --- a/Tests/RunCMake/CommandLine/DeprecateVS10-WARN-ON-stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -^CMake Warning: - The "Visual Studio 10 2010" generator is deprecated and will be removed in - a future version of CMake. - - Add CMAKE_WARN_VS10=OFF to the cache to disable this warning.$ diff --git a/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-OFF.cmake b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-OFF.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-OFF.cmake diff --git a/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON-stderr.txt b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON-stderr.txt new file mode 100644 index 0000000..9080942 --- /dev/null +++ b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON-stderr.txt @@ -0,0 +1,5 @@ +^CMake Warning: + The "Visual Studio 11 2012" generator is deprecated and will be removed in + a future version of CMake. + + Add CMAKE_WARN_VS11=OFF to the cache to disable this warning.$ diff --git a/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON.cmake b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/CommandLine/DeprecateVS11-WARN-ON.cmake diff --git a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt index 6a932f1..1452c9b 100644 --- a/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt +++ b/Tests/RunCMake/CommandLine/E_capabilities-stdout.txt @@ -1 +1 @@ -^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":4}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"version":{.*}}$ +^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":4}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"tls":(true|false),"version":{.*}}$ diff --git a/Tests/RunCMake/CommandLine/E_env-equal.cmake b/Tests/RunCMake/CommandLine/E_env-equal.cmake new file mode 100644 index 0000000..3f18bb6 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env-equal.cmake @@ -0,0 +1,15 @@ +if (NOT DEFINED ENV{TEST_ENV_EXPECTED}) + if (NOT DEFINED ENV{TEST_ENV}) + message(STATUS "TEST_ENV is correctly not set in environment") + else () + message(FATAL_ERROR "TEST_ENV is incorrectly set in environment") + endif () +else () + if (NOT DEFINED ENV{TEST_ENV}) + message(FATAL_ERROR "TEST_ENV is incorrectly not set in environment") + elseif ("$ENV{TEST_ENV}" STREQUAL "$ENV{TEST_ENV_EXPECTED}") + message(STATUS "TEST_ENV is correctly set in environment: $ENV{TEST_ENV}") + else () + message(FATAL_ERROR "TEST_ENV is incorrectly set in environment!\n\tactual: $ENV{TEST_ENV}\n\texpected: $ENV{TEST_ENV_EXPECTED}") + endif () +endif () diff --git a/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-result.txt b/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-stderr.txt b/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-stderr.txt new file mode 100644 index 0000000..ccfdeab --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-bad-operation-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error: Error: Unrecognized environment manipulation argument: unknown + +cmake -E env: invalid parameter to --modify: TEST_ENV=unknown:$ diff --git a/Tests/RunCMake/CommandLine/E_env_modify-cmake_list-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-cmake_list-stdout.txt new file mode 100644 index 0000000..ad42f56 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-cmake_list-stdout.txt @@ -0,0 +1 @@ +^-- TEST_ENV is correctly set in environment: exp;ect;ed$ diff --git a/Tests/RunCMake/CommandLine/E_env_modify-path_list-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-path_list-stdout.txt new file mode 100644 index 0000000..49572a3 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-path_list-stdout.txt @@ -0,0 +1 @@ +^-- TEST_ENV is correctly set in environment: exp[;:]ect[;:]ed$ diff --git a/Tests/RunCMake/CommandLine/E_env_modify-reset-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-reset-stdout.txt new file mode 100644 index 0000000..a60f1bf --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-reset-stdout.txt @@ -0,0 +1 @@ +^-- TEST_ENV is correctly set in environment: expected$ diff --git a/Tests/RunCMake/CommandLine/E_env_modify-reset-to-unset-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-reset-to-unset-stdout.txt new file mode 100644 index 0000000..a1d5c01 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-reset-to-unset-stdout.txt @@ -0,0 +1 @@ +^-- TEST_ENV is correctly not set in environment$ diff --git a/Tests/RunCMake/CommandLine/E_env_modify-set-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-set-stdout.txt new file mode 100644 index 0000000..feff117 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-set-stdout.txt @@ -0,0 +1 @@ +^-- TEST_ENV is correctly set in environment: 1$ diff --git a/Tests/RunCMake/CommandLine/E_env_modify-string-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-string-stdout.txt new file mode 100644 index 0000000..a60f1bf --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-string-stdout.txt @@ -0,0 +1 @@ +^-- TEST_ENV is correctly set in environment: expected$ diff --git a/Tests/RunCMake/CommandLine/E_env_modify-unset-stdout.txt b/Tests/RunCMake/CommandLine/E_env_modify-unset-stdout.txt new file mode 100644 index 0000000..a1d5c01 --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-unset-stdout.txt @@ -0,0 +1 @@ +^-- TEST_ENV is correctly not set in environment$ diff --git a/Tests/RunCMake/CommandLine/E_env_modify-with-double-dash-result.txt b/Tests/RunCMake/CommandLine/E_env_modify-with-double-dash-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-with-double-dash-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-result.txt b/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-stderr.txt b/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-stderr.txt new file mode 100644 index 0000000..8d98f9d --- /dev/null +++ b/Tests/RunCMake/CommandLine/E_env_modify-without-double-dash-stderr.txt @@ -0,0 +1 @@ +.* diff --git a/Tests/RunCMake/CommandLine/P_working-dir.cmake b/Tests/RunCMake/CommandLine/P_working-dir.cmake index 4ea0293..e2c0378 100644 --- a/Tests/RunCMake/CommandLine/P_working-dir.cmake +++ b/Tests/RunCMake/CommandLine/P_working-dir.cmake @@ -9,6 +9,11 @@ foreach(d CMAKE_BINARY_DIR CMAKE_CURRENT_BINARY_DIR CMAKE_SOURCE_DIR CMAKE_CURRE if(EXPECTED_WORKING_DIR STREQUAL "${${d}}") message(STATUS "${d} is the expected working directory (${EXPECTED_WORKING_DIR})") else() - message(FATAL_ERROR "${d} = \"${${d}}\" is not the expected working directory (${EXPECTED_WORKING_DIR})") + get_filename_component(resolved "${EXPECTED_WORKING_DIR}" REALPATH) + if(resolved STREQUAL "${${d}}") + message(STATUS "${d} is the expected working directory (${resolved}) after symlink resolution") + else() + message(FATAL_ERROR "${d} = \"${${d}}\" is not the expected working directory (${EXPECTED_WORKING_DIR})") + endif() endif() endforeach() diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index fc05b2d..a2eeddf 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -744,6 +744,10 @@ run_cmake_command(E_cat-without-double-dash ${CMAKE_COMMAND} -E cat "-file-start unset(RunCMake_TEST_COMMAND_WORKING_DIRECTORY) unset(out) +# Unset environment variables that are used for testing cmake -E +unset(ENV{TEST_ENV}) +unset(ENV{TEST_ENV_EXPECTED}) + run_cmake_command(E_env-no-command0 ${CMAKE_COMMAND} -E env) run_cmake_command(E_env-no-command1 ${CMAKE_COMMAND} -E env TEST_ENV=1) run_cmake_command(E_env-bad-arg1 ${CMAKE_COMMAND} -E env -bad-arg1) @@ -758,6 +762,56 @@ file(COPY_FILE "${EXIT_CODE_EXE}" "${RunCMake_BINARY_DIR}/env=${exit_code}") run_cmake_command(E_env-with-double-dash ${CMAKE_COMMAND} -E env TEST_ENV=1 -- "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit) run_cmake_command(E_env-without-double-dash ${CMAKE_COMMAND} -E env TEST_ENV=1 "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit) +## Tests of env --modify +# Repeat the same tests as above +run_cmake_command(E_env_modify-set ${CMAKE_COMMAND} -E env --modify TEST_ENV=set:1 ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-set.cmake) +run_cmake_command(E_env_modify-unset ${CMAKE_COMMAND} -E env --modify TEST_ENV=set:1 ${CMAKE_COMMAND} -E env --modify TEST_ENV=unset: ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-unset.cmake) +run_cmake_command(E_env_modify-with-double-dash ${CMAKE_COMMAND} -E env --modify TEST_ENV=set:1 -- "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit) +run_cmake_command(E_env_modify-without-double-dash ${CMAKE_COMMAND} -E env --modify TEST_ENV=set:1 "${RunCMake_BINARY_DIR}/env=${exit_code}" zero_exit) + +# Test environment modification commands +run_cmake_command(E_env_modify-reset + ${CMAKE_COMMAND} -E env TEST_ENV=expected + ${CMAKE_COMMAND} -E env TEST_ENV_EXPECTED=expected TEST_ENV=bad_value --modify TEST_ENV=reset: + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake) + +run_cmake_command(E_env_modify-reset-to-unset + ${CMAKE_COMMAND} -E env --unset=TEST_ENV --unset=TEST_ENV_EXPECTED + ${CMAKE_COMMAND} -E env TEST_ENV=bad_value --modify TEST_ENV=reset: + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake) + +run_cmake_command(E_env_modify-string + ${CMAKE_COMMAND} -E env TEST_ENV_EXPECTED=expected + --modify TEST_ENV=unset: + --modify TEST_ENV=string_append:ect + --modify TEST_ENV=string_prepend:exp + --modify TEST_ENV=string_append:ed + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake) + +if (WIN32) + set(SEP "\\;") +else () + set(SEP ":") +endif () + +run_cmake_command(E_env_modify-path_list + ${CMAKE_COMMAND} -E env "TEST_ENV_EXPECTED=exp${SEP}ect${SEP}ed" + --modify TEST_ENV=unset: + --modify TEST_ENV=path_list_append:ect + --modify TEST_ENV=path_list_prepend:exp + --modify TEST_ENV=path_list_append:ed + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake) + +run_cmake_command(E_env_modify-cmake_list + ${CMAKE_COMMAND} -E env "TEST_ENV_EXPECTED=exp\\;ect\\;ed" + --modify TEST_ENV=unset: + --modify TEST_ENV=cmake_list_append:ect + --modify TEST_ENV=cmake_list_prepend:exp + --modify TEST_ENV=cmake_list_append:ed + ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/E_env-equal.cmake) + +run_cmake_command(E_env_modify-bad-operation ${CMAKE_COMMAND} -E env --modify TEST_ENV=unknown:) + run_cmake_command(E_md5sum-dir ${CMAKE_COMMAND} -E md5sum .) run_cmake_command(E_sha1sum-dir ${CMAKE_COMMAND} -E sha1sum .) run_cmake_command(E_sha224sum-dir ${CMAKE_COMMAND} -E sha224sum .) @@ -924,6 +978,8 @@ set(RunCMake_TEST_OPTIONS --debug-trycompile) run_cmake(debug-trycompile) unset(RunCMake_TEST_OPTIONS) +run_cmake(trycompile-clean) + function(run_cmake_depends) set(RunCMake_TEST_SOURCE_DIR "${RunCMake_SOURCE_DIR}/cmake_depends") set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/cmake_depends-build") @@ -941,8 +997,8 @@ set(CMAKE_DEPENDS_CHECK_C set(CMAKE_RELATIVE_PATH_TOP_SOURCE \"${RunCMake_TEST_SOURCE_DIR}\") set(CMAKE_RELATIVE_PATH_TOP_BINARY \"${RunCMake_TEST_BINARY_DIR}\") ") - run_cmake_command(cmake_depends ${CMAKE_COMMAND} -E cmake_depends - "Unix Makefiles" + run_cmake_command(cmake_depends ${CMAKE_COMMAND} -E env VERBOSE=1 + ${CMAKE_COMMAND} -E cmake_depends "Unix Makefiles" ${RunCMake_TEST_SOURCE_DIR} ${RunCMake_TEST_SOURCE_DIR} ${RunCMake_TEST_BINARY_DIR} ${RunCMake_TEST_BINARY_DIR} ${RunCMake_TEST_BINARY_DIR}/CMakeFiles/DepTarget.dir/DependInfo.cmake @@ -1016,9 +1072,9 @@ set(RunCMake_TEST_OPTIONS --profiling-format=google-trace --profiling-output=${P run_cmake(ProfilingTest) unset(RunCMake_TEST_OPTIONS) -if(RunCMake_GENERATOR MATCHES "^Visual Studio 10 2010") - run_cmake_with_options(DeprecateVS10-WARN-ON -DCMAKE_WARN_VS10=ON) - unset(ENV{CMAKE_WARN_VS10}) - run_cmake(DeprecateVS10-WARN-ON) - run_cmake_with_options(DeprecateVS10-WARN-OFF -DCMAKE_WARN_VS10=OFF) +if(RunCMake_GENERATOR MATCHES "^Visual Studio 11 2012") + run_cmake_with_options(DeprecateVS11-WARN-ON -DCMAKE_WARN_VS11=ON) + unset(ENV{CMAKE_WARN_VS11}) + run_cmake(DeprecateVS11-WARN-ON) + run_cmake_with_options(DeprecateVS11-WARN-OFF -DCMAKE_WARN_VS11=OFF) endif() diff --git a/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt b/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt index 8fe092b..cf972a8 100644 --- a/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt +++ b/Tests/RunCMake/CommandLine/cmake_depends-stdout.txt @@ -1 +1 @@ -^Scanning dependencies of target DepTarget$ +Scanning dependencies of target DepTarget$ diff --git a/Tests/RunCMake/CommandLine/debug-trycompile-stderr.txt b/Tests/RunCMake/CommandLine/debug-trycompile-stderr.txt new file mode 100644 index 0000000..e987300 --- /dev/null +++ b/Tests/RunCMake/CommandLine/debug-trycompile-stderr.txt @@ -0,0 +1,11 @@ +^CMake Debug Log at [^ +]*/Modules/CMakeDetermineCompilerABI.cmake:[0-9]+ \(try_compile\): + Executing try_compile \(CMAKE_C_ABI_COMPILED\) in: + + [^ +]*/Tests/RunCMake/CommandLine/debug-trycompile-build/CMakeFiles/CMakeScratch/TryCompile-[^/]+ +Call Stack \(most recent call first\): + [^ +]*/Modules/CMakeTestCCompiler.cmake:[0-9]+ \(CMAKE_DETERMINE_COMPILER_ABI\) + debug-trycompile.cmake:[0-9]+ \(enable_language\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/CommandLine/debug-trycompile.cmake b/Tests/RunCMake/CommandLine/debug-trycompile.cmake index a3835a7..9619ba8 100644 --- a/Tests/RunCMake/CommandLine/debug-trycompile.cmake +++ b/Tests/RunCMake/CommandLine/debug-trycompile.cmake @@ -1,5 +1,8 @@ enable_language(C) + # Look for a source tree left by enable_language internal checks. -if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeTmp/CMakeLists.txt) +set(scratch ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeScratch) +file(GLOB_RECURSE remnants ${scratch}/TryCompile-*/CMakeLists.txt) +if(NOT remnants) message(FATAL_ERROR "--debug-trycompile should leave the source behind") endif() diff --git a/Tests/RunCMake/CommandLine/trycompile-clean.cmake b/Tests/RunCMake/CommandLine/trycompile-clean.cmake new file mode 100644 index 0000000..11ec2b9 --- /dev/null +++ b/Tests/RunCMake/CommandLine/trycompile-clean.cmake @@ -0,0 +1,8 @@ +enable_language(C) + +# Look for a source tree left by enable_language internal checks. +set(scratch ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CMakeScratch) +file(GLOB_RECURSE remnants ${scratch}/TryCompile-*/*) +if(remnants) + message(FATAL_ERROR "try_compile should not leave artifacts behind") +endif() diff --git a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake index 84d0479..e6a2605 100644 --- a/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake +++ b/Tests/RunCMake/CompilerLauncher/RunCMakeTest.cmake @@ -17,7 +17,8 @@ endfunction() function(run_compiler_launcher_env lang) string(REGEX REPLACE "-.*" "" core_lang "${lang}") - set(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER} "${CMAKE_COMMAND};-E;env;USED_LAUNCHER=1") + # Use the noop genexp $<PATH:...> genexp to validate genexp support. + set(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER} "$<PATH:CMAKE_PATH,${CMAKE_COMMAND}>;-E;env;USED_LAUNCHER=1") run_compiler_launcher(${lang}) unset(ENV{CMAKE_${core_lang}_COMPILER_LAUNCHER}) endfunction() diff --git a/Tests/RunCMake/CompilerTest/C-stdout.txt b/Tests/RunCMake/CompilerTest/C-stdout.txt new file mode 100644 index 0000000..ce5d80e --- /dev/null +++ b/Tests/RunCMake/CompilerTest/C-stdout.txt @@ -0,0 +1,2 @@ +-- Check for working C compiler: [^ +]* - works diff --git a/Tests/RunCMake/CompilerTest/C.cmake b/Tests/RunCMake/CompilerTest/C.cmake new file mode 100644 index 0000000..8e9d70c --- /dev/null +++ b/Tests/RunCMake/CompilerTest/C.cmake @@ -0,0 +1,3 @@ +# Pretend the ABI check failed in order to force the fall-back test to run. +set(CMAKE_C_ABI_COMPILED FALSE) +enable_language(C) diff --git a/Tests/RunCMake/CompilerTest/CMakeLists.txt b/Tests/RunCMake/CompilerTest/CMakeLists.txt new file mode 100644 index 0000000..aba1016 --- /dev/null +++ b/Tests/RunCMake/CompilerTest/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.24) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/CompilerTest/CUDA-stdout.txt b/Tests/RunCMake/CompilerTest/CUDA-stdout.txt new file mode 100644 index 0000000..00d35df --- /dev/null +++ b/Tests/RunCMake/CompilerTest/CUDA-stdout.txt @@ -0,0 +1,2 @@ +-- Check for working CUDA compiler: [^ +]* - works diff --git a/Tests/RunCMake/CompilerTest/CUDA.cmake b/Tests/RunCMake/CompilerTest/CUDA.cmake new file mode 100644 index 0000000..e8c19a0 --- /dev/null +++ b/Tests/RunCMake/CompilerTest/CUDA.cmake @@ -0,0 +1,3 @@ +# Pretend the ABI check failed in order to force the fall-back test to run. +set(CMAKE_CUDA_ABI_COMPILED FALSE) +enable_language(CUDA) diff --git a/Tests/RunCMake/CompilerTest/CXX-stdout.txt b/Tests/RunCMake/CompilerTest/CXX-stdout.txt new file mode 100644 index 0000000..513fd85 --- /dev/null +++ b/Tests/RunCMake/CompilerTest/CXX-stdout.txt @@ -0,0 +1,2 @@ +-- Check for working CXX compiler: [^ +]* - works diff --git a/Tests/RunCMake/CompilerTest/CXX.cmake b/Tests/RunCMake/CompilerTest/CXX.cmake new file mode 100644 index 0000000..e17cc9d --- /dev/null +++ b/Tests/RunCMake/CompilerTest/CXX.cmake @@ -0,0 +1,3 @@ +# Pretend the ABI check failed in order to force the fall-back test to run. +set(CMAKE_CXX_ABI_COMPILED FALSE) +enable_language(CXX) diff --git a/Tests/RunCMake/CompilerTest/Fortran-stdout.txt b/Tests/RunCMake/CompilerTest/Fortran-stdout.txt new file mode 100644 index 0000000..d871fea --- /dev/null +++ b/Tests/RunCMake/CompilerTest/Fortran-stdout.txt @@ -0,0 +1,2 @@ +-- Check for working Fortran compiler: [^ +]* - works diff --git a/Tests/RunCMake/CompilerTest/Fortran.cmake b/Tests/RunCMake/CompilerTest/Fortran.cmake new file mode 100644 index 0000000..8c83bd7 --- /dev/null +++ b/Tests/RunCMake/CompilerTest/Fortran.cmake @@ -0,0 +1,3 @@ +# Pretend the ABI check failed in order to force the fall-back test to run. +set(CMAKE_Fortran_ABI_COMPILED FALSE) +enable_language(Fortran) diff --git a/Tests/RunCMake/CompilerTest/HIP-stdout.txt b/Tests/RunCMake/CompilerTest/HIP-stdout.txt new file mode 100644 index 0000000..8b3baa7 --- /dev/null +++ b/Tests/RunCMake/CompilerTest/HIP-stdout.txt @@ -0,0 +1,2 @@ +-- Check for working HIP compiler: [^ +]* - works diff --git a/Tests/RunCMake/CompilerTest/HIP.cmake b/Tests/RunCMake/CompilerTest/HIP.cmake new file mode 100644 index 0000000..e56b77a --- /dev/null +++ b/Tests/RunCMake/CompilerTest/HIP.cmake @@ -0,0 +1,3 @@ +# Pretend the ABI check failed in order to force the fall-back test to run. +set(CMAKE_HIP_ABI_COMPILED FALSE) +enable_language(HIP) diff --git a/Tests/RunCMake/CompilerTest/ISPC-stdout.txt b/Tests/RunCMake/CompilerTest/ISPC-stdout.txt new file mode 100644 index 0000000..7e45c91 --- /dev/null +++ b/Tests/RunCMake/CompilerTest/ISPC-stdout.txt @@ -0,0 +1,3 @@ +-- The ISPC compiler identification is [^ +]* +-- Configuring done diff --git a/Tests/RunCMake/CompilerTest/ISPC.cmake b/Tests/RunCMake/CompilerTest/ISPC.cmake new file mode 100644 index 0000000..3ce7b28 --- /dev/null +++ b/Tests/RunCMake/CompilerTest/ISPC.cmake @@ -0,0 +1,3 @@ +# Pretend the ABI check failed in order to force the fall-back test to run. +set(CMAKE_ISPC_ABI_COMPILED FALSE) +enable_language(ISPC) diff --git a/Tests/RunCMake/CompilerTest/OBJC-stdout.txt b/Tests/RunCMake/CompilerTest/OBJC-stdout.txt new file mode 100644 index 0000000..23f5120 --- /dev/null +++ b/Tests/RunCMake/CompilerTest/OBJC-stdout.txt @@ -0,0 +1,2 @@ +-- Check for working OBJC compiler: [^ +]* - works diff --git a/Tests/RunCMake/CompilerTest/OBJC.cmake b/Tests/RunCMake/CompilerTest/OBJC.cmake new file mode 100644 index 0000000..5ec842c --- /dev/null +++ b/Tests/RunCMake/CompilerTest/OBJC.cmake @@ -0,0 +1,3 @@ +# Pretend the ABI check failed in order to force the fall-back test to run. +set(CMAKE_OBJC_ABI_COMPILED FALSE) +enable_language(OBJC) diff --git a/Tests/RunCMake/CompilerTest/OBJCXX-stdout.txt b/Tests/RunCMake/CompilerTest/OBJCXX-stdout.txt new file mode 100644 index 0000000..8291904 --- /dev/null +++ b/Tests/RunCMake/CompilerTest/OBJCXX-stdout.txt @@ -0,0 +1,2 @@ +-- Check for working OBJCXX compiler: [^ +]* - works diff --git a/Tests/RunCMake/CompilerTest/OBJCXX.cmake b/Tests/RunCMake/CompilerTest/OBJCXX.cmake new file mode 100644 index 0000000..49df0aa --- /dev/null +++ b/Tests/RunCMake/CompilerTest/OBJCXX.cmake @@ -0,0 +1,3 @@ +# Pretend the ABI check failed in order to force the fall-back test to run. +set(CMAKE_OBJCXX_ABI_COMPILED FALSE) +enable_language(OBJCXX) diff --git a/Tests/RunCMake/CompilerTest/RunCMakeTest.cmake b/Tests/RunCMake/CompilerTest/RunCMakeTest.cmake new file mode 100644 index 0000000..2dd9c7f --- /dev/null +++ b/Tests/RunCMake/CompilerTest/RunCMakeTest.cmake @@ -0,0 +1,25 @@ +include(RunCMake) + +run_cmake(C) +run_cmake(CXX) + +if(CMake_TEST_CUDA) + run_cmake(CUDA) +endif() + +if(CMake_TEST_Fortran) + run_cmake(Fortran) +endif() + +if(CMake_TEST_HIP) + run_cmake(HIP) +endif() + +if(CMake_TEST_ISPC) + run_cmake(ISPC) +endif() + +if(CMake_TEST_OBJC) + run_cmake(OBJC) + run_cmake(OBJCXX) +endif() diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake b/Tests/RunCMake/Configure/CopyFileABI-override.cmake index c633555..67f6ed5 100644 --- a/Tests/RunCMake/Configure/FailCopyFileABI-override.cmake +++ b/Tests/RunCMake/Configure/CopyFileABI-override.cmake @@ -1,5 +1,6 @@ # Change the executable suffix that try_compile will use for -# COPY_FILE but not inside the test project. This forces failure. +# COPY_FILE but not inside the test project, to verify +# we can handle envs that try and break everything get_property(in_try_compile GLOBAL PROPERTY IN_TRY_COMPILE) if(NOT in_try_compile) set(CMAKE_EXECUTABLE_SUFFIX .missing) diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt b/Tests/RunCMake/Configure/CopyFileABI-stdout.txt index 92fe233..6a856a4 100644 --- a/Tests/RunCMake/Configure/FailCopyFileABI-stdout.txt +++ b/Tests/RunCMake/Configure/CopyFileABI-stdout.txt @@ -1,4 +1,4 @@ -- Detecting C compiler ABI info --- Detecting C compiler ABI info - failed.* +-- Detecting C compiler ABI info - done.* -- Configuring done -- Generating done diff --git a/Tests/RunCMake/Configure/FailCopyFileABI.cmake b/Tests/RunCMake/Configure/CopyFileABI.cmake index 74efd97..4eee100 100644 --- a/Tests/RunCMake/Configure/FailCopyFileABI.cmake +++ b/Tests/RunCMake/Configure/CopyFileABI.cmake @@ -1,2 +1,2 @@ -set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/FailCopyFileABI-override.cmake) +set(CMAKE_USER_MAKE_RULES_OVERRIDE_C ${CMAKE_CURRENT_SOURCE_DIR}/CopyFileABI-override.cmake) enable_language(C) diff --git a/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake b/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake deleted file mode 100644 index db0cb0a..0000000 --- a/Tests/RunCMake/Configure/FailCopyFileABI-check.cmake +++ /dev/null @@ -1,14 +0,0 @@ -set(log "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/CMakeError.log") -if(EXISTS "${log}") - file(READ "${log}" error_log) -else() - set(error_log "") -endif() -string(REPLACE "\r\n" "\n" regex "Cannot copy output executable.* -to destination specified by COPY_FILE:.* -Unable to find the executable at any of: - .*\\.missing") -if(NOT error_log MATCHES "${regex}") - string(REGEX REPLACE "\n" "\n " error_log " ${error_log}") - set(RunCMake_TEST_FAILED "Log file:\n ${log}\ndoes not have expected COPY_FILE failure message:\n${error_log}") -endif() diff --git a/Tests/RunCMake/Configure/RunCMakeTest.cmake b/Tests/RunCMake/Configure/RunCMakeTest.cmake index 9fd4499..750fa3c 100644 --- a/Tests/RunCMake/Configure/RunCMakeTest.cmake +++ b/Tests/RunCMake/Configure/RunCMakeTest.cmake @@ -1,9 +1,9 @@ include(RunCMake) run_cmake(ContinueAfterError) +run_cmake(CopyFileABI) run_cmake(CustomTargetAfterError) run_cmake(ErrorLogs) -run_cmake(FailCopyFileABI) # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/RerunCMake-build) diff --git a/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build1-stdout.txt b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build1-stdout.txt new file mode 100644 index 0000000..2c223f7 --- /dev/null +++ b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build1-stdout.txt @@ -0,0 +1,6 @@ +.*-- once: configure +.*-- once: build +.*-- once: install +.*-- always: configure +.*-- always: build +.*-- always: install diff --git a/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build2-stdout.txt b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build2-stdout.txt new file mode 100644 index 0000000..d697490 --- /dev/null +++ b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS-build2-stdout.txt @@ -0,0 +1,2 @@ +.*-- always: build +.*-- always: install diff --git a/Tests/RunCMake/ExternalProject/BUILD_ALWAYS.cmake b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS.cmake new file mode 100644 index 0000000..2e5fc6f --- /dev/null +++ b/Tests/RunCMake/ExternalProject/BUILD_ALWAYS.cmake @@ -0,0 +1,20 @@ +include(ExternalProject) + +ExternalProject_Add(once + DOWNLOAD_COMMAND "" + CONFIGURE_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/once-configure.cmake + BUILD_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/once-build.cmake + INSTALL_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/once-install.cmake + ) + +ExternalProject_Add(always + DEPENDS once + DOWNLOAD_COMMAND "" + CONFIGURE_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/always-configure.cmake + BUILD_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/always-build.cmake + COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${CMAKE_CURRENT_LIST_FILE} + "${CMAKE_CURRENT_BINARY_DIR}/byproduct.txt" + BUILD_BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/byproduct.txt" + BUILD_ALWAYS 1 + INSTALL_COMMAND "${CMAKE_COMMAND}" -P ${CMAKE_CURRENT_BINARY_DIR}/always-install.cmake + ) diff --git a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake index 2588d6c..f152f5b 100644 --- a/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/ExternalProject/RunCMakeTest.cmake @@ -177,6 +177,28 @@ if(doSubstitutionTest) __ep_test_with_build(Substitutions) endif() +function(__ep_test_BUILD_ALWAYS) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/BUILD_ALWAYS-build) + run_cmake(BUILD_ALWAYS) + set(RunCMake_TEST_NO_CLEAN 1) + file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-configure.cmake" [[message(STATUS "once: configure")]]) + file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-build.cmake" [[message(STATUS "once: build")]]) + file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-install.cmake" [[message(STATUS "once: install")]]) + file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-configure.cmake" [[message(STATUS "always: configure")]]) + file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-build.cmake" [[message(STATUS "always: build")]]) + file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-install.cmake" [[message(STATUS "always: install")]]) + run_cmake_command(BUILD_ALWAYS-build1 ${CMAKE_COMMAND} --build . --target always) + file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-configure.cmake" [[message(FATAL_ERROR "once: configure should not run again")]]) + file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-build.cmake" [[message(FATAL_ERROR "once: build should not run again")]]) + file(WRITE "${RunCMake_TEST_BINARY_DIR}/once-install.cmake" [[message(FATAL_ERROR "once: install should not run again")]]) + if(NOT RunCMake_GENERATOR MATCHES "^(Xcode|Visual Studio 9 )") + # The Xcode and VS 9 build systems decide to run this every time. + file(WRITE "${RunCMake_TEST_BINARY_DIR}/always-configure.cmake" [[message(FATAL_ERROR "always: configure should not run again")]]) + endif() + run_cmake_command(BUILD_ALWAYS-build2 ${CMAKE_COMMAND} --build . --target always) +endfunction() +__ep_test_BUILD_ALWAYS() + function(__ep_test_CONFIGURE_HANDLED_BY_BUILD) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CONFIGURE_HANDLED_BY_BUILD-build) run_cmake(CONFIGURE_HANDLED_BY_BUILD) diff --git a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake index 28b8570..3b095a6 100644 --- a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake +++ b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake @@ -38,9 +38,15 @@ run_cmake(exact_1.2.3.5) unset(RunCMake_DEFAULT_stderr) # check if searching for a version 0 works -list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=0") +set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=0") run_cmake(exact_0_matching) +set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=") +run_cmake(empty_version) + +set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}") +run_cmake(exact_1_no_version_var) + # check custom error message set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DCustomMessage_VERSION=1.2.3.4") run_cmake(custom_message_1) diff --git a/Tests/RunCMake/FPHSA/empty_version-result.txt b/Tests/RunCMake/FPHSA/empty_version-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/FPHSA/empty_version-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/FPHSA/empty_version-stderr.txt b/Tests/RunCMake/FPHSA/empty_version-stderr.txt new file mode 100644 index 0000000..3b60c7a --- /dev/null +++ b/Tests/RunCMake/FPHSA/empty_version-stderr.txt @@ -0,0 +1,9 @@ +^CMake Error at [^ +]*/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\): + Could NOT find Pseudo: \(Required is at least version "1"\) \(found TRUE\) +Call Stack \(most recent call first\): + [^ +]*/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(_FPHSA_FAILURE_MESSAGE\) + FindPseudo.cmake:[0-9]+ \(find_package_handle_standard_args\) + empty_version.cmake:[0-9]+ \(find_package\) + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/FPHSA/empty_version.cmake b/Tests/RunCMake/FPHSA/empty_version.cmake new file mode 100644 index 0000000..7b7ff34 --- /dev/null +++ b/Tests/RunCMake/FPHSA/empty_version.cmake @@ -0,0 +1 @@ +find_package(Pseudo 1 REQUIRED) diff --git a/Tests/RunCMake/FPHSA/exact_1_no_version_var-stdout.txt b/Tests/RunCMake/FPHSA/exact_1_no_version_var-stdout.txt new file mode 100644 index 0000000..7cbdf6e --- /dev/null +++ b/Tests/RunCMake/FPHSA/exact_1_no_version_var-stdout.txt @@ -0,0 +1 @@ +-- Found Pseudo: TRUE \(Required is at least version "1"\) diff --git a/Tests/RunCMake/FPHSA/exact_1_no_version_var.cmake b/Tests/RunCMake/FPHSA/exact_1_no_version_var.cmake new file mode 100644 index 0000000..7b7ff34 --- /dev/null +++ b/Tests/RunCMake/FPHSA/exact_1_no_version_var.cmake @@ -0,0 +1 @@ +find_package(Pseudo 1 REQUIRED) diff --git a/Tests/RunCMake/FetchContent/IncludesNonSystem/CMakeLists.txt b/Tests/RunCMake/FetchContent/IncludesNonSystem/CMakeLists.txt new file mode 100644 index 0000000..f319e01 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesNonSystem/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(barnonsys STATIC bar.cpp) +add_executable(foononsys foo.cpp) diff --git a/Tests/RunCMake/FetchContent/IncludesNonSystem/bar.cpp b/Tests/RunCMake/FetchContent/IncludesNonSystem/bar.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesNonSystem/bar.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesNonSystem/foo.cpp b/Tests/RunCMake/FetchContent/IncludesNonSystem/foo.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesNonSystem/foo.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/CMakeLists.txt b/Tests/RunCMake/FetchContent/IncludesSystem/CMakeLists.txt new file mode 100644 index 0000000..60c6820 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/CMakeLists.txt @@ -0,0 +1,20 @@ +project(SystemSub NONE) + +FetchContent_Declare( + SubSub1 + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/SubSub1 + SYSTEM +) +FetchContent_Declare( + SubSub2 + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/SubSub2 +) + +FetchContent_MakeAvailable(SubSub1 SubSub2) + +add_library(bar STATIC bar.cpp) + +add_library(foo STATIC foo.cpp) +set_target_properties(foo PROPERTIES SYSTEM OFF) + +add_executable(zot zot.cpp) diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/CMakeLists.txt b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/CMakeLists.txt new file mode 100644 index 0000000..291339b --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(subsub1bar STATIC bar.cpp) + +add_library(subsub1foo STATIC foo.cpp) +set_target_properties(subsub1foo PROPERTIES SYSTEM OFF) + +add_executable(subsub1zot zot.cpp) diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/bar.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/bar.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/bar.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/foo.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/foo.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/foo.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/zot.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/zot.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub1/zot.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/CMakeLists.txt b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/CMakeLists.txt new file mode 100644 index 0000000..5755742 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(subsub2bar STATIC bar.cpp) + +add_library(subsub2foo STATIC foo.cpp) +set_target_properties(subsub2foo PROPERTIES SYSTEM OFF) + +add_executable(subsub2zot zot.cpp) diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/bar.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/bar.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/bar.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/foo.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/foo.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/foo.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/zot.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/zot.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/SubSub2/zot.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/bar.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/bar.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/bar.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/foo.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/foo.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/foo.cpp diff --git a/Tests/RunCMake/FetchContent/IncludesSystem/zot.cpp b/Tests/RunCMake/FetchContent/IncludesSystem/zot.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FetchContent/IncludesSystem/zot.cpp diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake index a7ccf83..bb27491 100644 --- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake +++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake @@ -8,6 +8,7 @@ run_cmake(FirstDetailsWin) run_cmake(DownloadTwice) run_cmake(DownloadFile) run_cmake(SameGenerator) +run_cmake(System) run_cmake(VarDefinitions) run_cmake(VarPassthroughs) run_cmake(GetProperties) diff --git a/Tests/RunCMake/FetchContent/System.cmake b/Tests/RunCMake/FetchContent/System.cmake new file mode 100644 index 0000000..c10e2af --- /dev/null +++ b/Tests/RunCMake/FetchContent/System.cmake @@ -0,0 +1,37 @@ +enable_language(CXX) + +include(FetchContent) + +FetchContent_Declare( + IncludesSystem + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/IncludesSystem + SYSTEM +) +FetchContent_MakeAvailable(IncludesSystem) + +FetchContent_Declare( + IncludesNonSystem + SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/IncludesNonSystem +) +FetchContent_MakeAvailable(IncludesNonSystem) + +function(check_target_system target expected_value) + get_target_property(var ${target} SYSTEM) + if ((var AND NOT expected_value) OR (NOT var AND expected_value)) + message(SEND_ERROR "\ +The 'SYSTEM' property of ${target} should be ${expected_value}, \ +but got ${var}") + endif() +endfunction() + +check_target_system(foo OFF) +check_target_system(bar ON) +check_target_system(zot ON) +check_target_system(subsub1foo OFF) +check_target_system(subsub1bar ON) +check_target_system(subsub1zot ON) +check_target_system(subsub2foo OFF) +check_target_system(subsub2bar ON) +check_target_system(subsub2zot ON) +check_target_system(foononsys OFF) +check_target_system(barnonsys OFF) diff --git a/Tests/RunCMake/FileAPI/CMakeLists.txt b/Tests/RunCMake/FileAPI/CMakeLists.txt index 44025d3..9a66cde 100644 --- a/Tests/RunCMake/FileAPI/CMakeLists.txt +++ b/Tests/RunCMake/FileAPI/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.13) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/FileAPI/ClientStateful-check.py b/Tests/RunCMake/FileAPI/ClientStateful-check.py index f3d20d1..28679bb 100644 --- a/Tests/RunCMake/FileAPI/ClientStateful-check.py +++ b/Tests/RunCMake/FileAPI/ClientStateful-check.py @@ -108,7 +108,11 @@ def check_query_json_empty(q): check_error_re(q, "value, object or array expected") def check_query_json_extra(q): - check_error_re(q, "Extra non-whitespace after JSON value") + if bool(os.environ.get("CMake_JSONCPP_PRE_1_7_5", "")) and is_dict(q) and sorted(q.keys()) == ["responses"]: + # jsoncpp < 1.7.5 did not diagnose extra non-whitespace characters + check_error(q["responses"], "'requests' member missing") + else: + check_error_re(q, "Extra non-whitespace after JSON value") def check_query_not_file(q): check_error_re(q, "failed to read from file") diff --git a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake index 61dce17..961b73a 100644 --- a/Tests/RunCMake/FileAPI/RunCMakeTest.cmake +++ b/Tests/RunCMake/FileAPI/RunCMakeTest.cmake @@ -39,6 +39,10 @@ if(RunCMake_GENERATOR_IS_MULTI_CONFIG) set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release\\;MinSizeRel\\;RelWithDebInfo") endif() +if(JsonCpp_VERSION_STRING AND JsonCpp_VERSION_STRING VERSION_LESS 1.7.5) + set(ENV{CMake_JSONCPP_PRE_1_7_5} 1) +endif() + run_cmake(Nothing) run_cmake(Empty) run_cmake(EmptyClient) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index d5f596e..b7623de 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -213,6 +213,16 @@ def check_directory(c): assert is_int(at["index"]) assert c["targets"][at["index"]]["name"] == et["index"] + if e.get("cxxModuleBmiTarget", None) is not None: + expected_keys.append("cxxModuleBmiTarget") + et = e["cxxModuleBmiTarget"] + at = a["cxxModuleBmiTarget"] + assert is_dict(at) + assert sorted(at.keys()) == ["id", "index"] + assert matches(at["id"], et["id"]) + assert is_int(at["index"]) + assert c["targets"][at["index"]]["name"] == et["index"] + if e["backtrace"] is not None: expected_keys.append("backtrace") check_backtrace(d, a["backtrace"], e["backtrace"]) @@ -654,6 +664,7 @@ def gen_check_directories(c, g): read_codemodel_json_data("directories/dir_dir.json"), read_codemodel_json_data("directories/external.json"), read_codemodel_json_data("directories/fileset.json"), + read_codemodel_json_data("directories/subdir.json"), ] if matches(g["name"], "^Visual Studio "): @@ -712,6 +723,7 @@ def gen_check_targets(c, g, inSource): read_codemodel_json_data("targets/c_shared_exe.json"), read_codemodel_json_data("targets/c_static_lib.json"), read_codemodel_json_data("targets/c_static_exe.json"), + read_codemodel_json_data("targets/c_subdir.json"), read_codemodel_json_data("targets/all_build_cxx.json"), read_codemodel_json_data("targets/zero_check_cxx.json"), diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json index 6514910..de8b177 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/alias.json @@ -10,7 +10,7 @@ "^cxx_alias_exe::@53632cba2752272bb008$" ], "projectName": "Alias", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": null, "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json index c89e4f9..e57191c 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/custom.json @@ -10,7 +10,7 @@ "^custom_tgt::@c11385ffed57b860da63$" ], "projectName": "Custom", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": null, "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json index 8052c1a..28f2b99 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/cxx.json @@ -16,7 +16,7 @@ "^cxx_static_lib::@a56b12a3f5c0529fb296$" ], "projectName": "Cxx", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": true, "installers": [ { diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json index 8509f08..2a3756e 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir.json @@ -7,7 +7,7 @@ ], "targetIds": null, "projectName": "codemodel-v2", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": null, "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json index 27184cd..12677f2 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/dir_dir.json @@ -5,7 +5,7 @@ "childSources": null, "targetIds": null, "projectName": "codemodel-v2", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": null, "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json index 6d2952d..f1199c3 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json @@ -9,7 +9,7 @@ "^generated_exe::@[0-9a-f]+$" ], "projectName": "External", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": true, "installers": [ { diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/fileset.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/fileset.json index 4774a13..c4df2ec 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/fileset.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/fileset.json @@ -8,7 +8,7 @@ "^c_headers_2::@6b8db101d64c125f29fe$" ], "projectName": "codemodel-v2", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": true, "installers": [ { diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json index 92b9526..8210d7f 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/imported.json @@ -13,7 +13,7 @@ "^link_imported_static_exe::@ba7eb709d0b48779c6c8$" ], "projectName": "Imported", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": true, "installers": [ { diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json index 90664dc..08edd64 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/interface.json @@ -9,7 +9,7 @@ "^iface_srcs::@25b7fa8ea00134654b85$" ], "projectName": "Interface", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": null, "installers": [] } diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/subdir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/subdir.json new file mode 100644 index 0000000..996da47 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/subdir.json @@ -0,0 +1,11 @@ +{ + "source": "^subdir$", + "build": "^subdir$", + "parentSource": "^\\.$", + "childSources": null, + "targetIds": null, + "projectName": "codemodel-v2", + "minimumCMakeVersion": "3.13", + "hasInstallRule": null, + "installers": [] +} diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json index e7b146f..aed07e2 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/directories/top.json @@ -11,7 +11,8 @@ "^object$", "^.*/Tests/RunCMake/FileAPIExternalSource$", "^dir$", - "^fileset$" + "^fileset$", + "^subdir$" ], "targetIds": [ "^ALL_BUILD::@6890427a1f51a3e7e1df$", @@ -22,10 +23,11 @@ "^c_shared_lib::@6890427a1f51a3e7e1df$", "^c_static_exe::@6890427a1f51a3e7e1df$", "^c_static_lib::@6890427a1f51a3e7e1df$", + "^c_subdir::@6890427a1f51a3e7e1df$", "^interface_exe::@6890427a1f51a3e7e1df$" ], "projectName": "codemodel-v2", - "minimumCMakeVersion": "3.12", + "minimumCMakeVersion": "3.13", "hasInstallRule": true, "installers": [ { @@ -48,7 +50,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 39, + "line": 42, "command": "install", "hasParent": true }, @@ -93,7 +95,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 42, + "line": 45, "command": "install", "hasParent": true }, @@ -141,7 +143,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 42, + "line": 45, "command": "install", "hasParent": true }, @@ -186,7 +188,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 42, + "line": 45, "command": "install", "hasParent": true }, @@ -230,7 +232,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 42, + "line": 45, "command": "install", "hasParent": true }, @@ -274,7 +276,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 47, + "line": 50, "command": "install", "hasParent": true }, @@ -321,7 +323,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 49, + "line": 52, "command": "install", "hasParent": true }, @@ -366,7 +368,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 50, + "line": 53, "command": "install", "hasParent": true }, @@ -415,7 +417,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 51, + "line": 54, "command": "install", "hasParent": true }, @@ -467,7 +469,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 52, + "line": 55, "command": "install", "hasParent": true }, @@ -516,7 +518,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 53, + "line": 56, "command": "install", "hasParent": true }, @@ -558,7 +560,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 54, + "line": 57, "command": "install", "hasParent": true }, @@ -600,7 +602,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 55, + "line": 58, "command": "install", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json index 0d6c4a1..151c0a8 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/projects/codemodel-v2.json @@ -14,7 +14,8 @@ "^\\.$", "^dir$", "^dir/dir$", - "^fileset$" + "^fileset$", + "^subdir$" ], "targetIds": [ "^ALL_BUILD::@6890427a1f51a3e7e1df$", @@ -26,6 +27,7 @@ "^c_shared_exe::@6890427a1f51a3e7e1df$", "^c_static_lib::@6890427a1f51a3e7e1df$", "^c_static_exe::@6890427a1f51a3e7e1df$", + "^c_subdir::@6890427a1f51a3e7e1df$", "^c_headers_1::@6b8db101d64c125f29fe$", "^c_headers_2::@6b8db101d64c125f29fe$" ] diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json index 4e772a7..0d45d07 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/all_build_top.json @@ -96,6 +96,10 @@ "backtrace": null }, { + "id": "^c_subdir::@6890427a1f51a3e7e1df$", + "backtrace": null + }, + { "id": "^c_static_exe::@6890427a1f51a3e7e1df$", "backtrace": null }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json index b4318dd..9a210ff 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json @@ -115,7 +115,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 42, + "line": 45, "command": "install", "hasParent": true }, @@ -145,7 +145,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 42, + "line": 45, "command": "install", "hasParent": true }, @@ -175,7 +175,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 47, + "line": 50, "command": "install", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json new file mode 100644 index 0000000..12ec917 --- /dev/null +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_subdir.json @@ -0,0 +1,150 @@ +{ + "name": "c_subdir", + "id": "^c_subdir::@6890427a1f51a3e7e1df$", + "directorySource": "^\\.$", + "projectName": "codemodel-v2", + "type": "STATIC_LIBRARY", + "isGeneratorProvided": null, + "sources": [ + { + "path": "^subdir/empty\\.c$", + "isGenerated": null, + "sourceGroupName": "Source Files", + "compileGroupLanguage": "C", + "backtrace": [ + { + "file": "^subdir/CMakeLists\\.txt$", + "line": 4, + "command": "target_sources", + "hasParent": true + }, + { + "file": "^subdir/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ], + "sourceGroups": [ + { + "name": "Source Files", + "sourcePaths": [ + "^subdir/empty\\.c$" + ] + } + ], + "compileGroups": [ + { + "language": "C", + "sourcePaths": [ + "^subdir/empty\\.c$" + ], + "includes": [ + { + "path": "^.*/Tests/RunCMake/FileAPI/subdir$", + "isSystem": null, + "backtrace": [ + { + "file": "^subdir/CMakeLists\\.txt$", + "line": 2, + "command": "target_include_directories", + "hasParent": true + }, + { + "file": "^subdir/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ], + "defines": [ + { + "define": "SUBDIR", + "backtrace": [ + { + "file": "^subdir/CMakeLists\\.txt$", + "line": 1, + "command": "target_compile_definitions", + "hasParent": true + }, + { + "file": "^subdir/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + } + ], + "compileCommandFragments": null + } + ], + "backtrace": [ + { + "file": "^codemodel-v2\\.cmake$", + "line": 17, + "command": "add_library", + "hasParent": true + }, + { + "file": "^codemodel-v2\\.cmake$", + "line": null, + "command": null, + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": 3, + "command": "include", + "hasParent": true + }, + { + "file": "^CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ], + "folder": null, + "nameOnDisk": "^(lib)?c_subdir\\.(a|lib)$", + "artifacts": [ + { + "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?c_subdir\\.(a|lib)$", + "_dllExtra": false + } + ], + "build": "^\\.$", + "source": "^\\.$", + "install": null, + "link": null, + "archive": { + "lto": null + }, + "dependencies": [ + { + "id": "^c_lib::@6890427a1f51a3e7e1df$", + "backtrace": [ + { + "file": "^subdir/CMakeLists\\.txt$", + "line": 3, + "command": "target_link_libraries", + "hasParent": true + }, + { + "file": "^subdir/CMakeLists\\.txt$", + "line": null, + "command": null, + "hasParent": false + } + ] + }, + { + "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$", + "backtrace": null + } + ] +} diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json index 5769f0c..16d074a 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json @@ -136,7 +136,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 39, + "line": 42, "command": "install", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json index 1fe4d67..03f4cb9 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json +++ b/Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json @@ -91,7 +91,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 42, + "line": 45, "command": "install", "hasParent": true }, @@ -121,7 +121,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 42, + "line": 45, "command": "install", "hasParent": true }, @@ -151,7 +151,7 @@ "backtrace": [ { "file": "^codemodel-v2\\.cmake$", - "line": 47, + "line": 50, "command": "install", "hasParent": true }, diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake index 019eb87..09db216 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake +++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake @@ -14,6 +14,9 @@ add_library(c_static_lib STATIC empty.c) add_executable(c_static_exe empty.c) target_link_libraries(c_static_exe PRIVATE c_static_lib) +add_library(c_subdir STATIC) +add_subdirectory(subdir) + add_subdirectory(cxx) add_subdirectory(alias) add_subdirectory(object) diff --git a/Tests/RunCMake/FileAPI/subdir/CMakeLists.txt b/Tests/RunCMake/FileAPI/subdir/CMakeLists.txt new file mode 100644 index 0000000..b8f4550 --- /dev/null +++ b/Tests/RunCMake/FileAPI/subdir/CMakeLists.txt @@ -0,0 +1,4 @@ +target_compile_definitions(c_subdir PRIVATE SUBDIR) +target_include_directories(c_subdir PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(c_subdir PRIVATE c_lib) +target_sources(c_subdir PRIVATE empty.c) diff --git a/Tests/RunCMake/FileAPI/subdir/empty.c b/Tests/RunCMake/FileAPI/subdir/empty.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/FileAPI/subdir/empty.c diff --git a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake index 3908f42..dad0dd3 100644 --- a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake +++ b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake @@ -13,6 +13,9 @@ run_cmake(zip) # Extracting only selected files or directories run_cmake(zip-filtered) +run_cmake(create-missing-args) +run_cmake(extract-missing-args) + run_cmake(unsupported-format) run_cmake(zip-with-bad-compression) run_cmake(7zip-with-bad-compression) diff --git a/Tests/RunCMake/File_Archive/create-missing-args-result.txt b/Tests/RunCMake/File_Archive/create-missing-args-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Archive/create-missing-args-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt b/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt new file mode 100644 index 0000000..fd026f9 --- /dev/null +++ b/Tests/RunCMake/File_Archive/create-missing-args-stderr.txt @@ -0,0 +1,19 @@ +^CMake Error at create-missing-args.cmake:[0-9]+ \(file\): + Error after keyword "COMPRESSION": + + missing required value + + Error after keyword "COMPRESSION_LEVEL": + + missing required value + + Error after keyword "FORMAT": + + missing required value + + Error after keyword "OUTPUT": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/File_Archive/create-missing-args.cmake b/Tests/RunCMake/File_Archive/create-missing-args.cmake new file mode 100644 index 0000000..a0c84d2 --- /dev/null +++ b/Tests/RunCMake/File_Archive/create-missing-args.cmake @@ -0,0 +1,8 @@ +file(ARCHIVE_CREATE + OUTPUT # missing output path + FORMAT # missing output format + COMPRESSION # missing compression type + COMPRESSION_LEVEL # missing compression level + MTIME # missing modification time + PATHS # no paths + ) diff --git a/Tests/RunCMake/File_Archive/extract-missing-args-result.txt b/Tests/RunCMake/File_Archive/extract-missing-args-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Archive/extract-missing-args-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt b/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt new file mode 100644 index 0000000..0c93ece --- /dev/null +++ b/Tests/RunCMake/File_Archive/extract-missing-args-stderr.txt @@ -0,0 +1,11 @@ +^CMake Error at extract-missing-args.cmake:[0-9]+ \(file\): + Error after keyword "DESTINATION": + + missing required value + + Error after keyword "INPUT": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/File_Archive/extract-missing-args.cmake b/Tests/RunCMake/File_Archive/extract-missing-args.cmake new file mode 100644 index 0000000..21c5d99 --- /dev/null +++ b/Tests/RunCMake/File_Archive/extract-missing-args.cmake @@ -0,0 +1,5 @@ +file(ARCHIVE_EXTRACT + INPUT # missing input + DESTINATION # missing destination + PATTERNS # no patterns + ) diff --git a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt index a6ea314..72292f9 100644 --- a/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt +++ b/Tests/RunCMake/File_Configure/BadArgContent-stderr.txt @@ -1,4 +1,7 @@ CMake Error at BadArgContent.cmake:[0-9]+ \(file\): - file CONFIGURE CONTENT option needs a value. + Error after keyword "CONTENT": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt index b5a924c..d793f48 100644 --- a/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt +++ b/Tests/RunCMake/File_Configure/BadArgOutput-stderr.txt @@ -1,4 +1,7 @@ CMake Error at BadArgOutput.cmake:[0-9]+ \(file\): - file CONFIGURE OUTPUT option needs a value. + Error after keyword "OUTPUT": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/File_Configure/NoArgContent-result.txt b/Tests/RunCMake/File_Configure/NoArgContent-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Configure/NoArgContent-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt b/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt new file mode 100644 index 0000000..2e8dd9a --- /dev/null +++ b/Tests/RunCMake/File_Configure/NoArgContent-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at NoArgContent.cmake:[0-9]+ \(file\): + file CONFIGURE CONTENT option is mandatory. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/File_Configure/NoArgContent.cmake b/Tests/RunCMake/File_Configure/NoArgContent.cmake new file mode 100644 index 0000000..cf52c46 --- /dev/null +++ b/Tests/RunCMake/File_Configure/NoArgContent.cmake @@ -0,0 +1 @@ +file(CONFIGURE OUTPUT "") diff --git a/Tests/RunCMake/File_Configure/NoArgOutput-result.txt b/Tests/RunCMake/File_Configure/NoArgOutput-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/File_Configure/NoArgOutput-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt b/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt new file mode 100644 index 0000000..53de48b --- /dev/null +++ b/Tests/RunCMake/File_Configure/NoArgOutput-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at NoArgOutput.cmake:[0-9]+ \(file\): + file CONFIGURE OUTPUT option is mandatory. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/File_Configure/NoArgOutput.cmake b/Tests/RunCMake/File_Configure/NoArgOutput.cmake new file mode 100644 index 0000000..77e9cdc --- /dev/null +++ b/Tests/RunCMake/File_Configure/NoArgOutput.cmake @@ -0,0 +1 @@ +file(CONFIGURE CONTENT "") diff --git a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake index 5022985..008ce67 100644 --- a/Tests/RunCMake/File_Configure/RunCMakeTest.cmake +++ b/Tests/RunCMake/File_Configure/RunCMakeTest.cmake @@ -9,6 +9,8 @@ run_cmake(DirOutput) run_cmake(NewLineStyle-NoArg) run_cmake(NewLineStyle-ValidArg) run_cmake(NewLineStyle-WrongArg) +run_cmake(NoArgOutput) +run_cmake(NoArgContent) run_cmake(SubDir) run_cmake(AtOnly) run_cmake(EscapeQuotes) diff --git a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt index e823b25..708e6be 100644 --- a/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt +++ b/Tests/RunCMake/File_Generate/EmptyCondition1-stderr.txt @@ -1,4 +1,7 @@ CMake Error at EmptyCondition1.cmake:2 \(file\): - file Incorrect arguments to GENERATE subcommand. + Error after keyword "CONDITION": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/File_Generate/InputAndContent-check.cmake b/Tests/RunCMake/File_Generate/InputAndContent-check.cmake new file mode 100644 index 0000000..5c9b803 --- /dev/null +++ b/Tests/RunCMake/File_Generate/InputAndContent-check.cmake @@ -0,0 +1,8 @@ +file(READ "${RunCMake_TEST_BINARY_DIR}/output-INPUT.txt" input) +if(NOT input MATCHES "INPUT file") + string(APPEND RunCMake_TEST_FAILED "INPUT incorrectly overridden by CONTENT") +endif() +file(READ "${RunCMake_TEST_BINARY_DIR}/output-CONTENT.txt" content) +if(NOT content MATCHES "CONTENT argument") + string(APPEND RunCMake_TEST_FAILED "CONTENT incorrectly overridden by INPUT") +endif() diff --git a/Tests/RunCMake/File_Generate/InputAndContent-input.txt b/Tests/RunCMake/File_Generate/InputAndContent-input.txt new file mode 100644 index 0000000..73f162b --- /dev/null +++ b/Tests/RunCMake/File_Generate/InputAndContent-input.txt @@ -0,0 +1 @@ +INPUT file diff --git a/Tests/RunCMake/File_Generate/InputAndContent.cmake b/Tests/RunCMake/File_Generate/InputAndContent.cmake new file mode 100644 index 0000000..9c3977a --- /dev/null +++ b/Tests/RunCMake/File_Generate/InputAndContent.cmake @@ -0,0 +1,10 @@ +file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-INPUT.txt" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/InputAndContent-input.txt" + CONTENT "CONTENT argument" +) +file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/output-CONTENT.txt" + CONTENT "CONTENT argument" + INPUT "${CMAKE_CURRENT_SOURCE_DIR}/InputAndContent-input.txt" +) diff --git a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt index bc71f2f..b1b7f80 100644 --- a/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt +++ b/Tests/RunCMake/File_Generate/NewLineStyle-NoArg-stderr.txt @@ -1,4 +1,7 @@ CMake Error at NewLineStyle-NoArg.cmake:[0-9]+ \(file\): - file Incorrect arguments to GENERATE subcommand. + Error after keyword "NEWLINE_STYLE": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake index be3bf04..5a670ae 100644 --- a/Tests/RunCMake/File_Generate/RunCMakeTest.cmake +++ b/Tests/RunCMake/File_Generate/RunCMakeTest.cmake @@ -17,6 +17,7 @@ run_cmake(EmptyCondition2) run_cmake(BadCondition) run_cmake(DebugEvaluate) run_cmake(GenerateSource) +run_cmake(InputAndContent) run_cmake(OutputNameMatchesSources) run_cmake(OutputNameMatchesObjects) run_cmake(OutputNameMatchesOtherSources) diff --git a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake index f479dcf..661ae3f 100644 --- a/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake @@ -24,6 +24,27 @@ endif() # We need a real pkg-config to run the test for get_variable. find_package(PkgConfig) if (PKG_CONFIG_FOUND) + string(FIND "${CMAKE_CURRENT_BINARY_DIR}" " " IS_SPACES_IN_PATH) + if(IS_SPACES_IN_PATH GREATER -1) + string(REPLACE " " "\\ " ESCAPED_ROOT "${CMAKE_CURRENT_BINARY_DIR}") + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/test_spaces.pc" " +libdir=${ESCAPED_ROOT} +Name: test_spaces.pc +Version: 0.0 +Description: test spaces +Libs: -L\${libdir} +") + set(PKG_CONFIG_PATH_SAVED "$ENV{PKG_CONFIG_PATH}") + set(ENV{PKG_CONFIG_PATH} "${CMAKE_CURRENT_BINARY_DIR}") + execute_process(COMMAND "${PKG_CONFIG_EXECUTABLE}" --libs test_spaces + ERROR_QUIET COMMAND_ERROR_IS_FATAL ANY + OUTPUT_VARIABLE test_spaces_LIBS) + set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH_SAVED}") + string(STRIP "${test_spaces_LIBS}" test_spaces_LIBS_STRIPPED) + if(NOT "${test_spaces_LIBS_STRIPPED}" STREQUAL "-L${ESCAPED_ROOT}") + set(PKG_CONFIG_DONT_SUPPORT_SPACES_IN_PATH TRUE) + endif() + endif() run_cmake(FindPkgConfig_GET_VARIABLE) run_cmake(FindPkgConfig_GET_VARIABLE_PREFIX_PATH) run_cmake(FindPkgConfig_GET_VARIABLE_PKGCONFIG_PATH) @@ -32,5 +53,7 @@ if (PKG_CONFIG_FOUND) run_cmake(FindPkgConfig_VERSION_OPERATORS) run_cmake(FindPkgConfig_GET_MATCHING_MODULE_NAME) run_cmake(FindPkgConfig_empty_target) - run_cmake(FindPkgConfig_LIBRARY_PATH) + if(NOT PKG_CONFIG_DONT_SUPPORT_SPACES_IN_PATH) + run_cmake(FindPkgConfig_LIBRARY_PATH) + endif() endif () diff --git a/Tests/RunCMake/Framework/FrameworkConsumption.cmake b/Tests/RunCMake/Framework/FrameworkConsumption.cmake index 4663166..58b70a3 100644 --- a/Tests/RunCMake/Framework/FrameworkConsumption.cmake +++ b/Tests/RunCMake/Framework/FrameworkConsumption.cmake @@ -13,3 +13,21 @@ set_target_properties(Gui PROPERTIES add_executable(app main.c) target_link_libraries(app PRIVATE Gui) + + +# Same test but with generation done in custom directories +add_library(Gui2 SHARED Gui.c "${input_header}") +set_target_properties(Gui2 PROPERTIES + PUBLIC_HEADER "${input_header}" + FRAMEWORK TRUE + LIBRARY_OUTPUT_DIRECTORY lib +) + +add_executable(app2 main2.c) +set_target_properties(Gui2 PROPERTIES + PUBLIC_HEADER "${input_header}" + FRAMEWORK TRUE + RUNTIME_OUTPUT_DIRECTORY bin +) + +target_link_libraries(app2 PRIVATE Gui2) diff --git a/Tests/RunCMake/Framework/main2.c b/Tests/RunCMake/Framework/main2.c new file mode 100644 index 0000000..11f4e4d --- /dev/null +++ b/Tests/RunCMake/Framework/main2.c @@ -0,0 +1,9 @@ + +#include <Gui2/Gui.h> + +int main() +{ + foo(); + + return 0; +} diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-result.txt b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-stderr.txt b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-stderr.txt new file mode 100644 index 0000000..fb61d4b --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error in CMakeLists.txt: + MSVC_DEBUG_INFORMATION_FORMAT value 'BogusValue' not known for this (C|CXX) + compiler. ++ +CMake Generate step failed\. Build files cannot be regenerated correctly\.$ diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW.cmake new file mode 100644 index 0000000..165ea38 --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NEW.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0141 NEW) +include(CMP0141-common.cmake) diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NoEffect.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NoEffect.cmake new file mode 100644 index 0000000..82754a9 --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-NoEffect.cmake @@ -0,0 +1,4 @@ +include(CMP0141-common.cmake) + +# Setting this policy after enable_language command has no effect. +cmake_policy(SET CMP0141 NEW) diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-OLD.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-OLD.cmake new file mode 100644 index 0000000..7bbe586 --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-OLD.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0141 OLD) +include(CMP0141-common.cmake) diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-WARN.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-WARN.cmake new file mode 100644 index 0000000..912112a --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-WARN.cmake @@ -0,0 +1,2 @@ + +include(CMP0141-common.cmake) diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-common.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-common.cmake new file mode 100644 index 0000000..8e43a25 --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMP0141-common.cmake @@ -0,0 +1,31 @@ +enable_language(CXX) + +cmake_policy(GET CMP0141 cmp0141) +if(cmp0141 STREQUAL "NEW") + if(NOT CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT) + message(SEND_ERROR "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT not set under NEW behavior") + endif() +else() + if(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT) + message(SEND_ERROR "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT is set under OLD behavior") + endif() +endif() + +if(cmp0141 STREQUAL "NEW") + if(CMAKE_CXX_FLAGS_DEBUG MATCHES "[/-]Zi( |$)") + message(SEND_ERROR "CMAKE_CXX_FLAGS_DEBUG has -Zi flags under NEW behavior.") + endif() + if(CMAKE_CXX_FLAGS_RELWITHDEBINFO MATCHES "[/-]Zi( |$)") + message(SEND_ERROR "CMAKE_CXX_FLAGS_RELWITHDEBINFO has -Zi flags under NEW behavior.") + endif() +else() + if(NOT (CMAKE_CXX_FLAGS_DEBUG MATCHES "[/-]Zi( |$)")) + message(SEND_ERROR "CMAKE_CXX_FLAGS_DEBUG does not have -Zi flags under OLD behavior.") + endif() + if(NOT (CMAKE_CXX_FLAGS_RELWITHDEBINFO MATCHES "[/-]Zi( |$)")) + message(SEND_ERROR "CMAKE_CXX_FLAGS_RELWITHDEBINFO does not have -Zi flags under OLD behavior.") + endif() +endif() + +set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT BogusValue) +add_library(foo empty.cxx) diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/CMakeLists.txt b/Tests/RunCMake/MSVCDebugInformationFormat/CMakeLists.txt new file mode 100644 index 0000000..aba1016 --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.24) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/RunCMakeTest.cmake b/Tests/RunCMake/MSVCDebugInformationFormat/RunCMakeTest.cmake new file mode 100644 index 0000000..f678acf --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/RunCMakeTest.cmake @@ -0,0 +1,6 @@ +include(RunCMake) + +run_cmake(CMP0141-WARN) +run_cmake(CMP0141-OLD) +run_cmake(CMP0141-NEW) +run_cmake(CMP0141-NoEffect) diff --git a/Tests/RunCMake/MSVCDebugInformationFormat/empty.cxx b/Tests/RunCMake/MSVCDebugInformationFormat/empty.cxx new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/MSVCDebugInformationFormat/empty.cxx diff --git a/Tests/RunCMake/Ninja/QtAutoMocSkipPch.cmake b/Tests/RunCMake/Ninja/QtAutoMocSkipPch.cmake new file mode 100644 index 0000000..059b917 --- /dev/null +++ b/Tests/RunCMake/Ninja/QtAutoMocSkipPch.cmake @@ -0,0 +1,17 @@ +enable_language(CXX) + +set(QtX Qt${with_qt_version}) + +find_package(${QtX} REQUIRED COMPONENTS Core) + +set(CMAKE_AUTOMOC ON) + +add_library(simple_lib SHARED simple_lib.cpp) +add_executable(app_with_qt app.cpp app_qt.cpp) + +target_link_libraries(app_with_qt PRIVATE simple_lib ${QtX}::Core) + +set_source_files_properties(app.cpp app_qt.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS ON) + +target_precompile_headers(app_with_qt PRIVATE [["QObject"]]) diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake index 2a5b556..9f078e6 100644 --- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake +++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake @@ -357,6 +357,22 @@ function(run_QtAutoMocDeps) run_ninja("${RunCMake_TEST_BINARY_DIR}") endif() endfunction() + +function(run_QtAutoMocSkipPch) + set(QtX Qt${CMake_TEST_Qt_version}) + if(CMake_TEST_${QtX}Core_Version VERSION_GREATER_EQUAL 5.15.0) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/QtAutoMocSkipPch-build) + run_cmake_with_options(QtAutoMocSkipPch + "-Dwith_qt_version=${CMake_TEST_Qt_version}" + "-D${QtX}_DIR=${${QtX}_DIR}" + "-D${QtX}Core_DIR=${${QtX}Core_DIR}" + "-DCMAKE_PREFIX_PATH:STRING=${CMAKE_PREFIX_PATH}" + ) + # Build the project. + run_ninja("${RunCMake_TEST_BINARY_DIR}") + endif() +endfunction() if(CMake_TEST_Qt_version) run_QtAutoMocDeps() + run_QtAutoMocSkipPch() endif() diff --git a/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake b/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake new file mode 100644 index 0000000..a1ae6ac --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CompileCommands-check.cmake @@ -0,0 +1,28 @@ +set(expected_compile_commands +[==[^\[ +{ + "directory": "[^ +]*(/Tests/RunCMake/NinjaMultiConfig/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\CompileCommands-build)", + "command": "[^ +]*Debug[^ +]*", + "file": "[^ +]*(/Tests/RunCMake/NinjaMultiConfig/main\.c|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\main\.c)" +}, +{ + "directory": "[^ +]*(/Tests/RunCMake/NinjaMultiConfig/CompileCommands-build|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\CompileCommands-build)", + "command": "[^ +]*Release[^ +]*", + "file": "[^ +]*(/Tests/RunCMake/NinjaMultiConfig/main\.c|\\\\Tests\\\\RunCMake\\\\NinjaMultiConfig\\\\main\.c)" +} +]$]==]) + +file(READ "${RunCMake_TEST_BINARY_DIR}/compile_commands.json" actual_compile_commands) +if(NOT actual_compile_commands MATCHES "${expected_compile_commands}") + string(REPLACE "\n" "\n " expected_compile_commands_formatted "${expected_compile_commands}") + string(REPLACE "\n" "\n " actual_compile_commands_formatted "${actual_compile_commands}") + string(APPEND RunCMake_TEST_FAILED "Expected compile_commands.json to match:\n ${expected_compile_commands_formatted}\nActual compile_commands.json:\n ${actual_compile_commands_formatted}\n") +endif() diff --git a/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake b/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake new file mode 100644 index 0000000..fc44d5a --- /dev/null +++ b/Tests/RunCMake/NinjaMultiConfig/CompileCommands.cmake @@ -0,0 +1,3 @@ +enable_language(C) + +add_executable(exe main.c) diff --git a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake index 738bc6c..c040e8f 100644 --- a/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake +++ b/Tests/RunCMake/NinjaMultiConfig/RunCMakeTest.cmake @@ -453,6 +453,11 @@ run_cmake_command(NoUnusedVariables ${CMAKE_COMMAND} ${CMAKE_CURRENT_LIST_DIR} "-DCMAKE_DEFAULT_BUILD_TYPE=Debug" "-DCMAKE_DEFAULT_CONFIGS=all" ) +unset(RunCMake_TEST_BINARY_DIR) + +set(RunCMake_TEST_OPTIONS "-DCMAKE_CONFIGURATION_TYPES=Debug\\;Release;-DCMAKE_CROSS_CONFIGS=all;-DCMAKE_EXPORT_COMPILE_COMMANDS=ON") +run_cmake(CompileCommands) +unset(RunCMake_TEST_OPTIONS) # CudaSimple uses separable compilation, which is currently only supported on NVCC. if(CMake_TEST_CUDA) diff --git a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake index 1410eae..df4ef1f 100644 --- a/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake +++ b/Tests/RunCMake/ParseImplicitLinkInfo/ParseImplicitLinkInfo.cmake @@ -155,6 +155,7 @@ foreach(t ${targets}) cmake_parse_implicit_link_info("${input}" implicit_libs idirs implicit_fwks log "${CMAKE_${lang}_IMPLICIT_OBJECT_REGEX}" + LANGUAGE ${lang} COMPUTE_IMPLICIT_OBJECTS implicit_objs) set(library_arch) diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake index 1c92ca0..ba9cc3b 100644 --- a/Tests/RunCMake/RunCMake.cmake +++ b/Tests/RunCMake/RunCMake.cmake @@ -1,8 +1,10 @@ -foreach(arg +foreach( + arg + IN ITEMS RunCMake_GENERATOR RunCMake_SOURCE_DIR RunCMake_BINARY_DIR - ) + ) if(NOT DEFINED ${arg}) message(FATAL_ERROR "${arg} not given!") endif() @@ -31,7 +33,7 @@ function(run_cmake test) set(platform_name msys) endif() - foreach(o out err) + foreach(o IN ITEMS out err) if(RunCMake-std${o}-file AND EXISTS ${top_src}/${RunCMake-std${o}-file}) file(READ ${top_src}/${RunCMake-std${o}-file} expect_std${o}) string(REGEX REPLACE "\n+$" "" expect_std${o} "${expect_std${o}}") @@ -162,6 +164,7 @@ function(run_cmake test) "|Your license to use PGI[^\n]*expired" "|Please obtain a new version at" "|contact PGI Sales at" + "|icp?c: remark #10441: The Intel\\(R\\) C\\+\\+ Compiler Classic \\(ICC\\) is deprecated" "|[^\n]*install_name_tool: warning: changes being made to the file will invalidate the code signature in:" "|[^\n]*xcodebuild[^\n]*DVTPlugInManager" @@ -176,7 +179,7 @@ function(run_cmake test) "|[^\n]*Bullseye Testing Technology" ")[^\n]*\n)+" ) - foreach(o out err) + foreach(o IN ITEMS out err) string(REGEX REPLACE "\r\n" "\n" actual_std${o} "${actual_std${o}}") string(REGEX REPLACE "${ignore_line_regex}" "\\1" actual_std${o} "${actual_std${o}}") string(REGEX REPLACE "\n+$" "" actual_std${o} "${actual_std${o}}") diff --git a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt index 97c3394..0d8e4c9 100644 --- a/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt +++ b/Tests/RunCMake/TargetPolicies/PolicyList-stderr.txt @@ -36,6 +36,7 @@ \* CMP0113 \* CMP0119 \* CMP0131 + \* CMP0142 Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/VS10Project/DebugInformationFormat-check.cmake b/Tests/RunCMake/VS10Project/DebugInformationFormat-check.cmake new file mode 100644 index 0000000..46af974 --- /dev/null +++ b/Tests/RunCMake/VS10Project/DebugInformationFormat-check.cmake @@ -0,0 +1,46 @@ +macro(DebugInformationFormat_check tgt Debug_expect Release_expect MinSizeRel_expect RelWithDebInfo_expect) + set(vcProjectFile "${RunCMake_TEST_BINARY_DIR}/${tgt}.vcxproj") + if(NOT EXISTS "${vcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj does not exist.") + return() + endif() + + set(Debug_actual "") + set(Release_actual "") + set(MinSizeRel_actual "") + set(RelWithDebInfo_actual "") + + file(STRINGS "${vcProjectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<ItemDefinitionGroup Condition=\"'\\$\\(Configuration\\)\\|\\$\\(Platform\\)'=='([^<>]+)\\|[A-Za-z0-9_]+'\">") + set(Configuration "${CMAKE_MATCH_1}") + endif() + if(line MATCHES "^ *<DebugInformationFormat>([^<>]+)</DebugInformationFormat>") + set(${Configuration}_actual "${CMAKE_MATCH_1}") + endif() + endforeach() + + if (NOT "${Debug_actual}" STREQUAL "${Debug_expect}") + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj Debug Configuration has DebugInformationFormat '${Debug_actual}', not '${Debug_expect}'.") + endif() + if (NOT "${Release_actual}" STREQUAL "${Release_expect}") + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj Release Configuration has DebugInformationFormat '${Release_actual}', not '${Release_expect}'.") + endif() + if (NOT "${MinSizeRel_actual}" STREQUAL "${MinSizeRel_expect}") + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj MinSizeRel Configuration has DebugInformationFormat '${MinSizeRel_actual}', not '${MinSizeRel_expect}'.") + endif() + if (NOT "${RelWithDebInfo_actual}" STREQUAL "${RelWithDebInfo_expect}") + set(RunCMake_TEST_FAILED "Project file ${tgt}.vcxproj RelWithDebInfo Configuration has DebugInformationFormat '${RelWithDebInfo_actual}', not '${RelWithDebInfo_expect}'.") + endif() +endmacro() + +DebugInformationFormat_check(default-C ProgramDatabase "" "" ProgramDatabase) +DebugInformationFormat_check(default-CXX ProgramDatabase "" "" ProgramDatabase) +DebugInformationFormat_check(empty-C "" "" "" "") +DebugInformationFormat_check(empty-CXX "" "" "" "") +DebugInformationFormat_check(Embedded-C OldStyle OldStyle OldStyle OldStyle) +DebugInformationFormat_check(Embedded-CXX OldStyle OldStyle OldStyle OldStyle) +DebugInformationFormat_check(ProgramDatabase-C ProgramDatabase ProgramDatabase ProgramDatabase ProgramDatabase) +DebugInformationFormat_check(ProgramDatabase-CXX ProgramDatabase ProgramDatabase ProgramDatabase ProgramDatabase) +DebugInformationFormat_check(EditAndContinue-C EditAndContinue EditAndContinue EditAndContinue EditAndContinue) +DebugInformationFormat_check(EditAndContinue-CXX EditAndContinue EditAndContinue EditAndContinue EditAndContinue) diff --git a/Tests/RunCMake/VS10Project/DebugInformationFormat.cmake b/Tests/RunCMake/VS10Project/DebugInformationFormat.cmake new file mode 100644 index 0000000..f670166 --- /dev/null +++ b/Tests/RunCMake/VS10Project/DebugInformationFormat.cmake @@ -0,0 +1,24 @@ +set(CMAKE_CONFIGURATION_TYPES Debug Release MinSizeRel RelWithDebInfo) +cmake_policy(SET CMP0141 NEW) +enable_language(C) +enable_language(CXX) + +add_library(default-C empty.c) +add_library(default-CXX empty.cxx) + +set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "") +add_library(empty-C empty.c) +add_library(empty-CXX empty.cxx) + +set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "Embedded") +add_library(Embedded-C empty.c) +add_library(Embedded-CXX empty.cxx) + +set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "ProgramDatabase") +add_library(ProgramDatabase-C empty.c) +add_library(ProgramDatabase-CXX empty.cxx) + +add_library(EditAndContinue-C empty.c) +set_property(TARGET EditAndContinue-C PROPERTY MSVC_DEBUG_INFORMATION_FORMAT "EditAndContinue") +add_library(EditAndContinue-CXX empty.cxx) +set_property(TARGET EditAndContinue-CXX PROPERTY MSVC_DEBUG_INFORMATION_FORMAT "EditAndContinue") diff --git a/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake index bcdc101..1701a36 100644 --- a/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake +++ b/Tests/RunCMake/VS10Project/InterfaceLibSources-check.cmake @@ -5,6 +5,7 @@ if(NOT EXISTS "${vcProjectFile}") endif() set(found_iface_h 0) +set(found_int_dir 0) file(STRINGS "${vcProjectFile}" lines) foreach(line IN LISTS lines) if(line MATCHES "<([A-Za-z0-9_]+) +Include=.*iface\\.h") @@ -19,7 +20,15 @@ foreach(line IN LISTS lines) endif() set(found_iface_h 1) endif() + if(line MATCHES "^ *<IntDir [^<>]+>[^<>]+</IntDir>") + set(found_int_dir 1) + endif() endforeach() if(NOT found_iface_h) set(RunCMake_TEST_FAILED "iface.h not referenced in\n ${vcProjectFile}") + return() +endif() +if(NOT found_int_dir) + set(RunCMake_TEST_FAILED "No references to IntDir in\n ${vcProjectFile}") + return() endif() diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index e540b9f..f027e94 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -88,3 +88,4 @@ run_cmake(VsDotnetStartupObject) run_cmake(VsDotnetTargetFramework) run_cmake(VsDotnetTargetFrameworkVersion) run_cmake(VsNoCompileBatching) +run_cmake(DebugInformationFormat) diff --git a/Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets-check.cmake b/Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets-check.cmake index 100f482..4d5508d 100644 --- a/Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets-check.cmake +++ b/Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets-check.cmake @@ -9,7 +9,7 @@ function(check_file target filename) if(filename MATCHES "^(.*)(\\.[a-z]+)$") set(header_filename "${CMAKE_MATCH_1}") endif() - set(expected_contents "#include <${header_filename}>\n") + set(expected_contents "#include <${header_filename}> // IWYU pragma: associated\n") file(READ "${full_filename}" actual_contents) if(NOT actual_contents STREQUAL expected_contents) diff --git a/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake b/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake index 9c9074e..22e2bb3 100644 --- a/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake +++ b/Tests/RunCMake/VsDotnetSdk/RunCMakeTest.cmake @@ -4,6 +4,7 @@ include(RunCMake) run_cmake(VsDotnetSdkCustomCommandsTarget) run_cmake(VsDotnetSdkCustomCommandsSource) run_cmake(VsDotnetSdkStartupObject) +run_cmake(VsDotnetSdkDefines) run_cmake(DotnetSdkVariables) function(run_VsDotnetSdk) diff --git a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake new file mode 100644 index 0000000..eaeba24 --- /dev/null +++ b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines-check.cmake @@ -0,0 +1,64 @@ +# +# Check C# VS project for required elements. +# +set(csProjectFile "${RunCMake_TEST_BINARY_DIR}/foo.csproj") +if(NOT EXISTS "${csProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${csProjectFile} does not exist.") + return() +endif() + + +set(inDebug FALSE) +set(inRelease FALSE) +set(debugOK FALSE) +set(releaseOK FALSE) + + +file(STRINGS "${csProjectFile}" lines) +foreach(line IN LISTS lines) + #message(STATUS ${line}) + if(line MATCHES "^ *<PropertyGroup .*Debug.*") + set(inDebug TRUE) + elseif(line MATCHES "^ *<PropertyGroup .*Release.*") + set(inRelease TRUE) + elseif(line MATCHES "^ *</PropertyGroup> *$") + set(inRelease FALSE) + set(inDebug FALSE) + elseif(inDebug AND + (line MATCHES "^ *<DefineConstants>.*MY_FOO_DEFINE.*</DefineConstants> *$") AND + (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_DEBUG.*</DefineConstants> *$") AND + (NOT (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_RELEASE.*</DefineConstants> *$")) AND + (NOT (line MATCHES "^ *<DefineConstants>.*MY_BAR_ASSIGNMENT=bar.*</DefineConstants> *$")) + ) + set(debugOK TRUE) + elseif(inRelease AND + (line MATCHES "^ *<DefineConstants>.*MY_FOO_DEFINE.*</DefineConstants> *$") AND + (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_RELEASE.*</DefineConstants> *$") AND + (NOT (line MATCHES "^ *<DefineConstants>.*DEFINE_ONLY_FOR_DEBUG.*</DefineConstants> *$")) AND + (NOT (line MATCHES "^ *<DefineConstants>.*MY_BAR_ASSIGNMENT=bar.*</DefineConstants> *$")) + ) + set(releaseOK TRUE) + endif() +endforeach() + +function(print_csprojfile) + file(STRINGS "${csProjectFile}" lines) + foreach(line IN LISTS lines) + message(STATUS ${line}) + endforeach() +endfunction() + + +if(NOT debugOK) + message(STATUS "Failed to set Debug configuration defines correctly.") + set(RunCMake_TEST_FAILED "Failed to set Debug configuration defines correctly.") + print_csprojfile() + return() +endif() + +if(NOT releaseOK) + message(STATUS "Failed to set Release configuration defines correctly.") + set(RunCMake_TEST_FAILED "Failed to set Release configuration defines correctly.") + print_csprojfile() + return() +endif() diff --git a/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake new file mode 100644 index 0000000..d89f19b --- /dev/null +++ b/Tests/RunCMake/VsDotnetSdk/VsDotnetSdkDefines.cmake @@ -0,0 +1,19 @@ +enable_language(CSharp) +if(NOT CMAKE_CSharp_COMPILER) + return() +endif() + +set(CMAKE_DOTNET_SDK "Microsoft.NET.Sdk") +set(CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION "net5.0") + +add_executable(foo csharponly.cs lib1.cs) + +# Issue 23376 +target_compile_definitions( + foo + PUBLIC + MY_FOO_DEFINE + "MY_BAR_ASSIGNMENT=bar" + $<$<CONFIG:Debug>:DEFINE_ONLY_FOR_DEBUG> + $<$<CONFIG:Release>:DEFINE_ONLY_FOR_RELEASE> +) diff --git a/Tests/RunCMake/XcodeProject/Clean.cmake b/Tests/RunCMake/XcodeProject/Clean.cmake new file mode 100644 index 0000000..1ab7e10 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/Clean.cmake @@ -0,0 +1,2 @@ +enable_language(C) +add_subdirectory(Clean) diff --git a/Tests/RunCMake/XcodeProject/Clean/CMakeLists.txt b/Tests/RunCMake/XcodeProject/Clean/CMakeLists.txt new file mode 100644 index 0000000..59e62cb --- /dev/null +++ b/Tests/RunCMake/XcodeProject/Clean/CMakeLists.txt @@ -0,0 +1 @@ +add_library(empty empty.c) diff --git a/Tests/RunCMake/XcodeProject/Clean/empty.c b/Tests/RunCMake/XcodeProject/Clean/empty.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/Clean/empty.c diff --git a/Tests/RunCMake/XcodeProject/EffectivePlatformNameOFF.cmake b/Tests/RunCMake/XcodeProject/EffectivePlatformNameOFF.cmake new file mode 100644 index 0000000..4a3bf56 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/EffectivePlatformNameOFF.cmake @@ -0,0 +1,12 @@ +enable_language(CXX) + +set_property(GLOBAL PROPERTY XCODE_EMIT_EFFECTIVE_PLATFORM_NAME OFF) + +set(CMAKE_MACOSX_BUNDLE true) + +add_library(library STATIC foo.cpp) + +add_executable(main main.cpp) +target_link_libraries(main library) + +install(TARGETS library ARCHIVE DESTINATION lib) diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index 128a9dc..fdf4411 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -1,5 +1,13 @@ include(RunCMake) +function(RunClean) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Clean-build) + run_cmake(Clean) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(Clean-build xcodebuild clean) +endfunction() +RunClean() + run_cmake(ExplicitCMakeLists) run_cmake(ImplicitCMakeLists) run_cmake(InterfaceLibSources) @@ -346,6 +354,7 @@ if(XCODE_VERSION VERSION_GREATER_EQUAL 6) endif() if(NOT XCODE_VERSION VERSION_LESS 5) + # XcodeMultiplatform set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/XcodeMultiplatform-build) set(RunCMake_TEST_NO_CLEAN 1) set(RunCMake_TEST_OPTIONS "${IOS_DEPLOYMENT_TARGET}") @@ -365,6 +374,23 @@ if(NOT XCODE_VERSION VERSION_LESS 5) unset(RunCMake_TEST_BINARY_DIR) unset(RunCMake_TEST_NO_CLEAN) unset(RunCMake_TEST_OPTIONS) + + # EffectivePlatformNameOFF + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EffectivePlatformNameOFF-build) + set(RunCMake_TEST_NO_CLEAN 1) + set(RunCMake_TEST_OPTIONS "-DCMAKE_SYSTEM_NAME=iOS" "-DCMAKE_OSX_SYSROOT=iphonesimulator") + + file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}") + file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}") + + run_cmake(EffectivePlatformNameOFF) + + run_cmake_command(EffectivePlatformNameOFF-iphonesimulator-build ${CMAKE_COMMAND} --build .) + run_cmake_command(EffectivePlatformNameOFF-iphonesimulator-install ${CMAKE_COMMAND} --build . --target install -- DESTDIR=${RunCMake_TEST_BINARY_DIR}/_install_iphonesimulator) + + unset(RunCMake_TEST_BINARY_DIR) + unset(RunCMake_TEST_NO_CLEAN) + unset(RunCMake_TEST_OPTIONS) endif() if(XCODE_VERSION VERSION_GREATER_EQUAL 8) diff --git a/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake b/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake index 71b7d8f..bec8790 100644 --- a/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake +++ b/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake @@ -12,6 +12,8 @@ set(found_target_library_FRAMEWORK_SEARCH_PATHS 0) set(found_inherited_FRAMEWORK_SEARCH_PATHS 0) set(found_project_LIBRARY_SEARCH_PATHS 0) set(found_target_library_LIBRARY_SEARCH_PATHS 0) +set(found_target_cmp0142old_LIBRARY_SEARCH_PATHS 0) +set(found_target_cmp0142new_LIBRARY_SEARCH_PATHS 0) set(found_inherited_LIBRARY_SEARCH_PATHS 0) file(STRINGS "${xcProjectFile}" lines) foreach(line IN LISTS lines) @@ -42,6 +44,12 @@ foreach(line IN LISTS lines) if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib/\$\(CONFIGURATION\)\$\(EFFECTIVE_PLATFORM_NAME\)(\\")?","(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib(\\")?","\$\(inherited\)"\);]]) set(found_target_library_LIBRARY_SEARCH_PATHS 1) endif() + if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathCMP0142OLD/\$\(CONFIGURATION\)\$\(EFFECTIVE_PLATFORM_NAME\)(\\")?","(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathCMP0142OLD(\\")?","\$\(inherited\)"\);]]) + set(found_target_cmp0142old_LIBRARY_SEARCH_PATHS 1) + endif() + if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathCMP0142NEW(\\")?","\$\(inherited\)"\);]]) + set(found_target_cmp0142new_LIBRARY_SEARCH_PATHS 1) + endif() if(line MATCHES [[LIBRARY_SEARCH_PATHS = \("\$\(inherited\)"\);]]) set(found_inherited_LIBRARY_SEARCH_PATHS 1) endif() @@ -68,6 +76,12 @@ endif() if(NOT found_target_library_LIBRARY_SEARCH_PATHS) string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'library' in\n ${xcProjectFile}\n") endif() +if(NOT found_target_cmp0142old_LIBRARY_SEARCH_PATHS) + string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'cmp0142old' in\n ${xcProjectFile}\n") +endif() +if(NOT found_target_cmp0142new_LIBRARY_SEARCH_PATHS) + string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'cmp0142new' in\n ${xcProjectFile}\n") +endif() if(found_inherited_LIBRARY_SEARCH_PATHS) string(APPEND RunCMake_TEST_FAILED "Found unexpected LIBRARY_SEARCH_PATHS inherited-only value in\n ${xcProjectFile}\n") endif() diff --git a/Tests/RunCMake/XcodeProject/SearchPaths.cmake b/Tests/RunCMake/XcodeProject/SearchPaths.cmake index ef97709..b469772 100644 --- a/Tests/RunCMake/XcodeProject/SearchPaths.cmake +++ b/Tests/RunCMake/XcodeProject/SearchPaths.cmake @@ -3,6 +3,8 @@ enable_language(C) file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathInc/TargetInc.framework") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib/TargetLib.framework") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathCMP0142OLD") +file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathCMP0142NEW") set(CMAKE_XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath") set(CMAKE_XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath") @@ -19,3 +21,11 @@ target_include_directories(include PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSe add_executable(library main.c) target_link_libraries(library PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib/TargetLib.framework") target_link_directories(library PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib") + +cmake_policy(SET CMP0142 OLD) +add_executable(cmp0142old main.c) +target_link_directories(cmp0142old PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathCMP0142OLD") + +cmake_policy(SET CMP0142 NEW) +add_executable(cmp0142new main.c) +target_link_directories(cmp0142new PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathCMP0142NEW") diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake index be44ecd..6bad527 100644 --- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty-check.cmake @@ -29,6 +29,8 @@ check_property("UNDEFINED_BEHAVIOUR_SANITIZER" "enableUBSanitizer") check_property("UNDEFINED_BEHAVIOUR_SANITIZER_STOP" "stopOnEveryUBSanitizerIssue") check_property("DISABLE_MAIN_THREAD_CHECKER" "disableMainThreadChecker") check_property("MAIN_THREAD_CHECKER_STOP" "stopOnEveryMainThreadCheckerIssue") +check_property("DISABLE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION" "enableGPUValidationMode") +check_property("ENABLE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION" "enableGPUShaderValidationMode") check_property("MALLOC_SCRIBBLE" "MallocScribble") check_property("MALLOC_GUARD_EDGES" "MallocGuardEdges") @@ -43,6 +45,8 @@ check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED" "enableGPUFrameCaptureMo check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_METAL" "enableGPUFrameCaptureMode=\"1\"") check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED_MIXED_CASE" "enableGPUFrameCaptureMode=\"3\"") check_property("ENABLE_GPU_FRAME_CAPTURE_MODE_METAL_MIXED_CASE" "enableGPUFrameCaptureMode=\"1\"") +check_property("LAUNCH_MODE_AUTO" "launchStyle=\"0\"") +check_property("LAUNCH_MODE_WAIT" "launchStyle=\"1\"") check_property("EXECUTABLE" "myExecutable") check_property("ARGUMENTS" [=["--foo"]=]) diff --git a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake index 126a9fc..267e379 100644 --- a/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake +++ b/Tests/RunCMake/XcodeProject/XcodeSchemaProperty.cmake @@ -32,12 +32,16 @@ function(create_scheme_for_property scheme property value) set_target_properties(${scheme} PROPERTIES XCODE_SCHEME_${property} "${value}") endfunction() +create_scheme_for_property(DISABLE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION ENABLE_GPU_API_VALIDATION OFF) +create_scheme_for_property(ENABLE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION ENABLE_GPU_SHADER_VALIDATION ON) create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_1 ENABLE_GPU_FRAME_CAPTURE_MODE 1) create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_3 ENABLE_GPU_FRAME_CAPTURE_MODE 3) create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED ENABLE_GPU_FRAME_CAPTURE_MODE Disabled) create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_METAL ENABLE_GPU_FRAME_CAPTURE_MODE Metal) create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_DISABLED_MIXED_CASE ENABLE_GPU_FRAME_CAPTURE_MODE DISAbled) create_scheme_for_property(ENABLE_GPU_FRAME_CAPTURE_MODE_METAL_MIXED_CASE ENABLE_GPU_FRAME_CAPTURE_MODE METal) +create_scheme_for_property(LAUNCH_MODE_AUTO LAUNCH_MODE AUTO) +create_scheme_for_property(LAUNCH_MODE_WAIT LAUNCH_MODE WAIT) create_scheme_for_property(EXECUTABLE EXECUTABLE myExecutable) create_scheme_for_property(ARGUMENTS ARGUMENTS "--foo;--bar=baz") create_scheme_for_property(ENVIRONMENT ENVIRONMENT "FOO=foo;BAR=bar") diff --git a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake index 951e03c..ddf45af 100644 --- a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake +++ b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake @@ -3,6 +3,7 @@ include(RunCMake) run_cmake(DoesNotExist) run_cmake(Missing) run_cmake(Function) +run_cmake(System) macro(run_cmake_install case) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${case}-build) diff --git a/Tests/RunCMake/add_subdirectory/System.cmake b/Tests/RunCMake/add_subdirectory/System.cmake new file mode 100644 index 0000000..45d7d9a --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System.cmake @@ -0,0 +1,22 @@ +enable_language(CXX) + +add_subdirectory(System SYSTEM) + +function(check_target_system target expected_value) + get_target_property(var ${target} SYSTEM) + if ((var AND NOT expected_value) OR (NOT var AND expected_value)) + message(SEND_ERROR "\ +The 'SYSTEM' property of ${target} should be ${expected_value}, \ +but got ${var}") + endif() +endfunction() + +check_target_system(foo OFF) +check_target_system(bar ON) +check_target_system(zot ON) +check_target_system(subsub1foo OFF) +check_target_system(subsub1bar ON) +check_target_system(subsub1zot ON) +check_target_system(subsub2foo OFF) +check_target_system(subsub2bar ON) +check_target_system(subsub2zot ON) diff --git a/Tests/RunCMake/add_subdirectory/System/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/System/CMakeLists.txt new file mode 100644 index 0000000..ef74e80 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/CMakeLists.txt @@ -0,0 +1,11 @@ +project(SystemSub NONE) + +add_subdirectory(SubSub1 SYSTEM) +add_subdirectory(SubSub2) + +add_library(bar STATIC bar.cpp) + +add_library(foo STATIC foo.cpp) +set_target_properties(foo PROPERTIES SYSTEM OFF) + +add_executable(zot zot.cpp) diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub1/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/System/SubSub1/CMakeLists.txt new file mode 100644 index 0000000..291339b --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/SubSub1/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(subsub1bar STATIC bar.cpp) + +add_library(subsub1foo STATIC foo.cpp) +set_target_properties(subsub1foo PROPERTIES SYSTEM OFF) + +add_executable(subsub1zot zot.cpp) diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub1/bar.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub1/bar.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/SubSub1/bar.cpp diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub1/foo.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub1/foo.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/SubSub1/foo.cpp diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub1/zot.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub1/zot.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/SubSub1/zot.cpp diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub2/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/System/SubSub2/CMakeLists.txt new file mode 100644 index 0000000..5755742 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/SubSub2/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(subsub2bar STATIC bar.cpp) + +add_library(subsub2foo STATIC foo.cpp) +set_target_properties(subsub2foo PROPERTIES SYSTEM OFF) + +add_executable(subsub2zot zot.cpp) diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub2/bar.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub2/bar.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/SubSub2/bar.cpp diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub2/foo.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub2/foo.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/SubSub2/foo.cpp diff --git a/Tests/RunCMake/add_subdirectory/System/SubSub2/zot.cpp b/Tests/RunCMake/add_subdirectory/System/SubSub2/zot.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/SubSub2/zot.cpp diff --git a/Tests/RunCMake/add_subdirectory/System/bar.cpp b/Tests/RunCMake/add_subdirectory/System/bar.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/bar.cpp diff --git a/Tests/RunCMake/add_subdirectory/System/foo.cpp b/Tests/RunCMake/add_subdirectory/System/foo.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/foo.cpp diff --git a/Tests/RunCMake/add_subdirectory/System/zot.cpp b/Tests/RunCMake/add_subdirectory/System/zot.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/add_subdirectory/System/zot.cpp diff --git a/Tests/RunCMake/block/CMakeLists.txt b/Tests/RunCMake/block/CMakeLists.txt new file mode 100644 index 0000000..45cd10e --- /dev/null +++ b/Tests/RunCMake/block/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.3...3.25) +project(${RunCMake_TEST} NONE) +include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/block/EndAlone-result.txt b/Tests/RunCMake/block/EndAlone-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/EndAlone-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/EndAlone-stderr.txt b/Tests/RunCMake/block/EndAlone-stderr.txt new file mode 100644 index 0000000..a588dd7 --- /dev/null +++ b/Tests/RunCMake/block/EndAlone-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at EndAlone.cmake:[0-9]+ \(endblock\): + Flow control statements are not properly nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/EndAlone.cmake b/Tests/RunCMake/block/EndAlone.cmake new file mode 100644 index 0000000..0c428a9 --- /dev/null +++ b/Tests/RunCMake/block/EndAlone.cmake @@ -0,0 +1 @@ +endblock() diff --git a/Tests/RunCMake/block/EndAloneWithArgument-result.txt b/Tests/RunCMake/block/EndAloneWithArgument-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/EndAloneWithArgument-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/EndAloneWithArgument-stderr.txt b/Tests/RunCMake/block/EndAloneWithArgument-stderr.txt new file mode 100644 index 0000000..c3d25a3 --- /dev/null +++ b/Tests/RunCMake/block/EndAloneWithArgument-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at EndAloneWithArgument.cmake:[0-9]+ \(endblock\): + Flow control statements are not properly nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/EndAloneWithArgument.cmake b/Tests/RunCMake/block/EndAloneWithArgument.cmake new file mode 100644 index 0000000..05df5b0 --- /dev/null +++ b/Tests/RunCMake/block/EndAloneWithArgument.cmake @@ -0,0 +1 @@ +endblock(WRONG_ARG) diff --git a/Tests/RunCMake/block/EndMissing-result.txt b/Tests/RunCMake/block/EndMissing-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/EndMissing-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/EndMissing-stderr.txt b/Tests/RunCMake/block/EndMissing-stderr.txt new file mode 100644 index 0000000..b9739a5 --- /dev/null +++ b/Tests/RunCMake/block/EndMissing-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at EndMissing.cmake:[0-9]+ \(block\): + Flow control statements are not properly nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/EndMissing.cmake b/Tests/RunCMake/block/EndMissing.cmake new file mode 100644 index 0000000..335b64e --- /dev/null +++ b/Tests/RunCMake/block/EndMissing.cmake @@ -0,0 +1 @@ +block() diff --git a/Tests/RunCMake/block/EndWithArgument-stderr.txt b/Tests/RunCMake/block/EndWithArgument-stderr.txt new file mode 100644 index 0000000..7586453 --- /dev/null +++ b/Tests/RunCMake/block/EndWithArgument-stderr.txt @@ -0,0 +1,9 @@ +CMake Warning \(dev\) in EndWithArgument.cmake: + A logical block closing on the line + + .+/Tests/RunCMake/block/EndWithArgument.cmake:[0-9]+ \(endblock\) + + has unexpected arguments. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/block/EndWithArgument.cmake b/Tests/RunCMake/block/EndWithArgument.cmake new file mode 100644 index 0000000..0641c9a --- /dev/null +++ b/Tests/RunCMake/block/EndWithArgument.cmake @@ -0,0 +1,2 @@ +block() +endblock(END_ARG) diff --git a/Tests/RunCMake/block/InvalidArgument-result.txt b/Tests/RunCMake/block/InvalidArgument-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/InvalidArgument-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/InvalidArgument-stderr.txt b/Tests/RunCMake/block/InvalidArgument-stderr.txt new file mode 100644 index 0000000..bee604b --- /dev/null +++ b/Tests/RunCMake/block/InvalidArgument-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at InvalidArgument.cmake:[0-9]+ \(block\): + block PROPAGATE cannot be specified without a new scope for VARIABLES +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/InvalidArgument.cmake b/Tests/RunCMake/block/InvalidArgument.cmake new file mode 100644 index 0000000..5269cd0 --- /dev/null +++ b/Tests/RunCMake/block/InvalidArgument.cmake @@ -0,0 +1,2 @@ +block(SCOPE_FOR POLICIES PROPAGATE VAR1) +endblock() diff --git a/Tests/RunCMake/block/InvalidNesting1-result.txt b/Tests/RunCMake/block/InvalidNesting1-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting1-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/InvalidNesting1-stderr.txt b/Tests/RunCMake/block/InvalidNesting1-stderr.txt new file mode 100644 index 0000000..6dfe0e1 --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting1-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at InvalidNesting1.cmake:[0-9]+ \(else\): + Flow control statements are not properly nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/InvalidNesting1.cmake b/Tests/RunCMake/block/InvalidNesting1.cmake new file mode 100644 index 0000000..27b7944 --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting1.cmake @@ -0,0 +1,6 @@ + +if (TRUE) + block() +else() + endblock() +endif() diff --git a/Tests/RunCMake/block/InvalidNesting2-result.txt b/Tests/RunCMake/block/InvalidNesting2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/InvalidNesting2-stderr.txt b/Tests/RunCMake/block/InvalidNesting2-stderr.txt new file mode 100644 index 0000000..71325b6 --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting2-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at InvalidNesting2.cmake:[0-9]+ \(endblock\): + Flow control statements are not properly nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/InvalidNesting2.cmake b/Tests/RunCMake/block/InvalidNesting2.cmake new file mode 100644 index 0000000..ae94cdc --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting2.cmake @@ -0,0 +1,6 @@ + +block() +if (TRUE) +elseif(FALSE) +endblock() +endif() diff --git a/Tests/RunCMake/block/InvalidNesting3-result.txt b/Tests/RunCMake/block/InvalidNesting3-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting3-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/InvalidNesting3-stderr.txt b/Tests/RunCMake/block/InvalidNesting3-stderr.txt new file mode 100644 index 0000000..344a931 --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting3-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at InvalidNesting3.cmake:[0-9]+ \(endwhile\): + Flow control statements are not properly nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/InvalidNesting3.cmake b/Tests/RunCMake/block/InvalidNesting3.cmake new file mode 100644 index 0000000..f692d24 --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting3.cmake @@ -0,0 +1,5 @@ + +while(TRUE) +block() +endwhile() +endblock() diff --git a/Tests/RunCMake/block/InvalidNesting4-result.txt b/Tests/RunCMake/block/InvalidNesting4-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting4-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/InvalidNesting4-stderr.txt b/Tests/RunCMake/block/InvalidNesting4-stderr.txt new file mode 100644 index 0000000..44d6364 --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting4-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at InvalidNesting4.cmake:[0-9]+ \(endblock\): + Flow control statements are not properly nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/InvalidNesting4.cmake b/Tests/RunCMake/block/InvalidNesting4.cmake new file mode 100644 index 0000000..6e8e0ae --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting4.cmake @@ -0,0 +1,5 @@ + +block() +foreach(item IN ITEMS A B) +endblock() +endforeach() diff --git a/Tests/RunCMake/block/InvalidNesting5-result.txt b/Tests/RunCMake/block/InvalidNesting5-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting5-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/InvalidNesting5-stderr.txt b/Tests/RunCMake/block/InvalidNesting5-stderr.txt new file mode 100644 index 0000000..976d2e1 --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting5-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at InvalidNesting5.cmake:[0-9]+ \(endfunction\): + Flow control statements are not properly nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/InvalidNesting5.cmake b/Tests/RunCMake/block/InvalidNesting5.cmake new file mode 100644 index 0000000..0479e8d --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting5.cmake @@ -0,0 +1,5 @@ + +function(FUNC) + block() +endfunction() +endblock() diff --git a/Tests/RunCMake/block/InvalidNesting6-result.txt b/Tests/RunCMake/block/InvalidNesting6-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting6-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/InvalidNesting6-stderr.txt b/Tests/RunCMake/block/InvalidNesting6-stderr.txt new file mode 100644 index 0000000..2d67b16 --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting6-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at InvalidNesting6.cmake:[0-9]+ \(endblock\): + Flow control statements are not properly nested. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/InvalidNesting6.cmake b/Tests/RunCMake/block/InvalidNesting6.cmake new file mode 100644 index 0000000..a1cb359 --- /dev/null +++ b/Tests/RunCMake/block/InvalidNesting6.cmake @@ -0,0 +1,5 @@ + + block() +macro(FUNC) +endblock() +endmacro() diff --git a/Tests/RunCMake/block/MissingArgument-result.txt b/Tests/RunCMake/block/MissingArgument-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/MissingArgument-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/MissingArgument-stderr.txt b/Tests/RunCMake/block/MissingArgument-stderr.txt new file mode 100644 index 0000000..d3e63ca --- /dev/null +++ b/Tests/RunCMake/block/MissingArgument-stderr.txt @@ -0,0 +1,7 @@ +CMake Error at MissingArgument.cmake:[0-9]+ \(block\): + Error after keyword "SCOPE_FOR": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/MissingArgument.cmake b/Tests/RunCMake/block/MissingArgument.cmake new file mode 100644 index 0000000..6018887 --- /dev/null +++ b/Tests/RunCMake/block/MissingArgument.cmake @@ -0,0 +1,2 @@ +block(SCOPE_FOR) +endblock() diff --git a/Tests/RunCMake/block/RunCMakeTest.cmake b/Tests/RunCMake/block/RunCMakeTest.cmake new file mode 100644 index 0000000..4260e76 --- /dev/null +++ b/Tests/RunCMake/block/RunCMakeTest.cmake @@ -0,0 +1,22 @@ +include(RunCMake) + +run_cmake(WrongArgument) +run_cmake(InvalidArgument) +run_cmake(MissingArgument) +run_cmake(WrongScope) +run_cmake(EndMissing) +run_cmake(EndWithArgument) +run_cmake(EndAlone) +run_cmake(EndAloneWithArgument) + +run_cmake(InvalidNesting1) +run_cmake(InvalidNesting2) +run_cmake(InvalidNesting3) +run_cmake(InvalidNesting4) +run_cmake(InvalidNesting5) +run_cmake(InvalidNesting6) + +run_cmake(Scope) +run_cmake(Scope-VARIABLES) +run_cmake(Scope-POLICIES) +run_cmake(Workflows) diff --git a/Tests/RunCMake/block/Scope-POLICIES.cmake b/Tests/RunCMake/block/Scope-POLICIES.cmake new file mode 100644 index 0000000..789b3d9 --- /dev/null +++ b/Tests/RunCMake/block/Scope-POLICIES.cmake @@ -0,0 +1,30 @@ + +set(VAR1 "OUTER1") +set(VAR2 "OUTER2") + +cmake_policy(SET CMP0139 NEW) + +# create a block with a new scope for policies +block(SCOPE_FOR POLICIES) + set(VAR1 "INNER1") + unset(VAR2) + set(VAR3 "INNER3") + + cmake_policy(SET CMP0139 OLD) +endblock() + +# check final values for variables +if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "INNER1") + message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}") +endif() +if(DEFINED VAR2) + message(SEND_ERROR "block/endblock: VAR2 is unexpectedly defined: ${VAR2}") +endif() +if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3") + message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}") +endif() + +cmake_policy(GET CMP0139 CMP0139_STATUS) +if(NOT CMP0139_STATUS STREQUAL "NEW") + message(SEND_ERROR "block/endblock: CMP0139 has unexpected value: ${CMP0139_STATUS}") +endif() diff --git a/Tests/RunCMake/block/Scope-VARIABLES.cmake b/Tests/RunCMake/block/Scope-VARIABLES.cmake new file mode 100644 index 0000000..140e638 --- /dev/null +++ b/Tests/RunCMake/block/Scope-VARIABLES.cmake @@ -0,0 +1,52 @@ + +set(VAR1 "OUTER1") +set(VAR2 "OUTER2") +set(VAR3 "OUTER3") +set(VAR4 "OUTER4") +set(VAR5 "OUTER5") + +set(VAR6 "CACHE6" CACHE STRING "") +set(VAR6 "OUTER6") + +cmake_policy(SET CMP0139 NEW) + +# create a block with a new scope for variables +block(SCOPE_FOR VARIABLES PROPAGATE VAR3 VAR4 VAR5 VAR6 VAR7) + set(VAR1 "INNER1") + set(VAR2 "INNER2" PARENT_SCOPE) + set(VAR3 "INNER3") + unset(VAR4) + unset(VAR6) + set(VAR7 "INNER7") + + cmake_policy(SET CMP0139 OLD) +endblock() + +# check final values for variables +if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "OUTER1") + message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}") +endif() +if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "INNER2") + message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}") +endif() +if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3") + message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}") +endif() +if(DEFINED VAR4) + message(SEND_ERROR "block/endblock: VAR4 is unexpectedly defined: ${VAR4}") +endif() +if(NOT DEFINED VAR5 OR NOT VAR5 STREQUAL "OUTER5") + message(SEND_ERROR "block/endblock: VAR5 has unexpected value: ${VAR5}") +endif() +unset(VAR6 CACHE) +if (DEFINED VAR6) + message(SEND_ERROR "block/endblock: VAR6 is unexpectedly defined: ${VAR6}") +endif() +if(NOT DEFINED VAR7 OR NOT VAR7 STREQUAL "INNER7") + message(SEND_ERROR "block/endblock: VAR7 has unexpected value: ${VAR7}") +endif() + +cmake_policy(GET CMP0139 CMP0139_STATUS) +if(NOT CMP0139_STATUS STREQUAL "OLD") + message(SEND_ERROR "block/endblock: CMP0139 has unexpected value: ${CMP0139_STATUS}") +endif() diff --git a/Tests/RunCMake/block/Scope.cmake b/Tests/RunCMake/block/Scope.cmake new file mode 100644 index 0000000..e1af50a --- /dev/null +++ b/Tests/RunCMake/block/Scope.cmake @@ -0,0 +1,52 @@ + +set(VAR1 "OUTER1") +set(VAR2 "OUTER2") +set(VAR3 "OUTER3") +set(VAR4 "OUTER4") +set(VAR5 "OUTER5") + +set(VAR6 "CACHE6" CACHE STRING "") +set(VAR6 "OUTER6") + +cmake_policy(SET CMP0139 NEW) + +# create a block with a new scope for variables and policies +block(PROPAGATE VAR3 VAR4 VAR5 VAR6 VAR7) + set(VAR1 "INNER1") + set(VAR2 "INNER2" PARENT_SCOPE) + set(VAR3 "INNER3") + unset(VAR4) + unset(VAR6) + set(VAR7 "INNER7") + + cmake_policy(SET CMP0139 OLD) +endblock() + +# check final values for variables +if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "OUTER1") + message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}") +endif() +if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "INNER2") + message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}") +endif() +if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3") + message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}") +endif() +if(DEFINED VAR4) + message(SEND_ERROR "block/endblock: VAR4 is unexpectedly defined: ${VAR4}") +endif() +if(NOT DEFINED VAR5 OR NOT VAR5 STREQUAL "OUTER5") + message(SEND_ERROR "block/endblock: VAR5 has unexpected value: ${VAR5}") +endif() +unset(VAR6 CACHE) +if (DEFINED VAR6) + message(SEND_ERROR "block/endblock: VAR6 is unexpectedly defined: ${VAR6}") +endif() +if(NOT DEFINED VAR7 OR NOT VAR7 STREQUAL "INNER7") + message(SEND_ERROR "block/endblock: VAR6 has unexpected value: ${VAR7}") +endif() + +cmake_policy(GET CMP0139 CMP0139_STATUS) +if(NOT CMP0139_STATUS STREQUAL "NEW") + message(SEND_ERROR "block/endblock: CMP0139 has unexpected value: ${CMP0139_STATUS}") +endif() diff --git a/Tests/RunCMake/block/Workflows.cmake b/Tests/RunCMake/block/Workflows.cmake new file mode 100644 index 0000000..cbf032e --- /dev/null +++ b/Tests/RunCMake/block/Workflows.cmake @@ -0,0 +1,78 @@ + +set(VAR1 "OUTER1") +set(VAR2 "OUTER2") +set(VAR3 "OUTER3") + +while (TRUE) + # create a block with a new scope for variables + block(SCOPE_FOR VARIABLES PROPAGATE VAR3) + set(VAR2 "INNER2" PARENT_SCOPE) + set(VAR3 "INNER3") + break() + endblock() +endwhile() + +# check final values for variables +if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "OUTER1") + message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}") +endif() +if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "INNER2") + message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}") +endif() +if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3") + message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}") +endif() + + + +set(VAR1 "OUTER1") +set(VAR2 "OUTER2") +set(VAR3 "OUTER3") + +function (OUTER) + # create a block with a new scope for variables + block(SCOPE_FOR VARIABLES PROPAGATE VAR3) + set(VAR2 "INNER2" PARENT_SCOPE) + set(VAR3 "INNER3") + return() + endblock() + set(VAR1 "INNER1" PARENT_SCOPE) +endfunction() +outer() + +# check final values for variables +if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "OUTER1") + message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}") +endif() +if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "OUTER2") + message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}") +endif() +if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "OUTER3") + message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}") +endif() + + + +set(VAR1 "OUTER1") +set(VAR2 "OUTER2") +set(VAR3 "OUTER3") + +foreach (id IN ITEMS 1 2 3) + # create a block with a new scope for variables + block(SCOPE_FOR VARIABLES PROPAGATE VAR${id}) + set(VAR${id} "INNER${id}") + continue() + set(VAR${id} "BAD${id}") + endblock() +endforeach() + +# check final values for variables +if(NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "INNER1") + message(SEND_ERROR "block/endblock: VAR1 has unexpected value: ${VAR1}") +endif() +if(NOT DEFINED VAR2 OR NOT VAR2 STREQUAL "INNER2") + message(SEND_ERROR "block/endblock: VAR2 has unexpected value: ${VAR2}") +endif() +if(NOT DEFINED VAR3 OR NOT VAR3 STREQUAL "INNER3") + message(SEND_ERROR "block/endblock: VAR3 has unexpected value: ${VAR3}") +endif() diff --git a/Tests/RunCMake/block/WrongArgument-result.txt b/Tests/RunCMake/block/WrongArgument-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/WrongArgument-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/WrongArgument-stderr.txt b/Tests/RunCMake/block/WrongArgument-stderr.txt new file mode 100644 index 0000000..56faea7 --- /dev/null +++ b/Tests/RunCMake/block/WrongArgument-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at WrongArgument.cmake:[0-9]+ \(block\): + block called with unsupported argument "WRONG_ARG" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/WrongArgument.cmake b/Tests/RunCMake/block/WrongArgument.cmake new file mode 100644 index 0000000..e460866 --- /dev/null +++ b/Tests/RunCMake/block/WrongArgument.cmake @@ -0,0 +1,2 @@ +block(WRONG_ARG) +endblock() diff --git a/Tests/RunCMake/block/WrongScope-result.txt b/Tests/RunCMake/block/WrongScope-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/block/WrongScope-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/block/WrongScope-stderr.txt b/Tests/RunCMake/block/WrongScope-stderr.txt new file mode 100644 index 0000000..dd2a1ef --- /dev/null +++ b/Tests/RunCMake/block/WrongScope-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at WrongScope.cmake:[0-9]+ \(block\): + block SCOPE_FOR unsupported scope "WRONG_SCOPE" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/block/WrongScope.cmake b/Tests/RunCMake/block/WrongScope.cmake new file mode 100644 index 0000000..97a6783 --- /dev/null +++ b/Tests/RunCMake/block/WrongScope.cmake @@ -0,0 +1,2 @@ +block(SCOPE_FOR WRONG_SCOPE) +endblock() diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt index 6a430f1..ea1566d 100644 --- a/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadQuery2-stderr.txt @@ -1,5 +1,7 @@ CMake Error at Registry_BadQuery2.cmake:[0-9]+ \(cmake_host_system_information\): - cmake_host_system_information missing expected value for argument\(s\) - "VALUE". + Error after keyword "VALUE": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt index 5eda4ff..f8c96d8 100644 --- a/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt +++ b/Tests/RunCMake/cmake_host_system_information/Registry_BadView1-stderr.txt @@ -1,5 +1,7 @@ CMake Error at Registry_BadView1.cmake:[0-9]+ \(cmake_host_system_information\): - cmake_host_system_information missing expected value for argument\(s\) - "VIEW". + Error after keyword "VIEW": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake index 6480b2e..38ce10b 100644 --- a/Tests/RunCMake/cmake_language/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_language/RunCMakeTest.cmake @@ -8,6 +8,7 @@ foreach(command IN ITEMS "if" "elseif" "else" "endif" "while" "endwhile" "foreach" "endforeach" + "block" "endblock" ) message(STATUS "Running call_invalid_command for ${command}...") run_cmake_with_options(call_invalid_command -Dcommand=${command}) @@ -42,6 +43,7 @@ foreach(command IN ITEMS "if" "elseif" "else" "endif" "while" "endwhile" "foreach" "endforeach" + "block" "endblock" "return" ) message(STATUS "Running defer_call_invalid_command for ${command}...") @@ -82,3 +84,61 @@ run_cmake(defer_get_call_id_var) run_cmake(defer_missing_arg) run_cmake(defer_missing_call) run_cmake(defer_unknown_option) + +# Default log level +run_cmake_command( + get_message_log_level_none + ${CMAKE_COMMAND} + -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake + ) + +# Log level from cache +run_cmake_command( + get_message_log_level_cache + ${CMAKE_COMMAND} + -DCMAKE_MESSAGE_LOG_LEVEL=TRACE + -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake + ) + +# Log level from regular variable +run_cmake_command( + get_message_log_level_var + ${CMAKE_COMMAND} + -DNEW_LOG_LEVEL=TRACE + -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake + ) + +# Log level from command line +run_cmake_command( + get_message_log_level_cli + ${CMAKE_COMMAND} + --log-level=DEBUG + -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake + ) + +# Log level from command line, it has higher priority over a cache variable +run_cmake_command( + get_message_log_level_cli_and_cache + ${CMAKE_COMMAND} + --log-level=DEBUG + -DCMAKE_MESSAGE_LOG_LEVEL=TRACE + -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake + ) + +# Log level from command line, it has higher priority over a regular variable +run_cmake_command( + get_message_log_level_cli_and_var + ${CMAKE_COMMAND} + --log-level=DEBUG + -DNEW_LOG_LEVEL=TRACE + -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake + ) + +# Log level from variable, it has higher priority over a cache variable +run_cmake_command( + get_message_log_level_var_and_cache + ${CMAKE_COMMAND} + -DNEW_LOG_LEVEL=DEBUG + -DCMAKE_MESSAGE_LOG_LEVEL=TRACE + -P ${RunCMake_SOURCE_DIR}/get_message_log_level.cmake + ) diff --git a/Tests/RunCMake/cmake_language/get_message_log_level.cmake b/Tests/RunCMake/cmake_language/get_message_log_level.cmake new file mode 100644 index 0000000..1740c1f --- /dev/null +++ b/Tests/RunCMake/cmake_language/get_message_log_level.cmake @@ -0,0 +1,5 @@ +if(NEW_LOG_LEVEL) + set(CMAKE_MESSAGE_LOG_LEVEL "${NEW_LOG_LEVEL}") +endif() +cmake_language(GET_MESSAGE_LOG_LEVEL log_level) +message(STATUS "log level is: ${log_level}") diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt new file mode 100644 index 0000000..cf1cd7b --- /dev/null +++ b/Tests/RunCMake/cmake_language/get_message_log_level_cache-stdout.txt @@ -0,0 +1 @@ +log level is: TRACE diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt new file mode 100644 index 0000000..4d6e1eb --- /dev/null +++ b/Tests/RunCMake/cmake_language/get_message_log_level_cli-stdout.txt @@ -0,0 +1 @@ +log level is: DEBUG diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt new file mode 100644 index 0000000..4d6e1eb --- /dev/null +++ b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_cache-stdout.txt @@ -0,0 +1 @@ +log level is: DEBUG diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt new file mode 100644 index 0000000..4d6e1eb --- /dev/null +++ b/Tests/RunCMake/cmake_language/get_message_log_level_cli_and_var-stdout.txt @@ -0,0 +1 @@ +log level is: DEBUG diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt new file mode 100644 index 0000000..92ffd34 --- /dev/null +++ b/Tests/RunCMake/cmake_language/get_message_log_level_none-stdout.txt @@ -0,0 +1 @@ +log level is: STATUS diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt new file mode 100644 index 0000000..cf1cd7b --- /dev/null +++ b/Tests/RunCMake/cmake_language/get_message_log_level_var-stdout.txt @@ -0,0 +1 @@ +log level is: TRACE diff --git a/Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt b/Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt new file mode 100644 index 0000000..4d6e1eb --- /dev/null +++ b/Tests/RunCMake/cmake_language/get_message_log_level_var_and_cache-stdout.txt @@ -0,0 +1 @@ +log level is: DEBUG diff --git a/Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt b/Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt new file mode 100644 index 0000000..ad7d134 --- /dev/null +++ b/Tests/RunCMake/cmake_path/BASE_DIRECTORY-no-arg-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at .+/cmake_path/call-cmake_path.cmake:[0-9]+ \(cmake_path\): + Error after keyword "BASE_DIRECTORY": + + missing required value diff --git a/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt new file mode 100644 index 0000000..f1b52cc --- /dev/null +++ b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-empty-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at .+/call-cmake_path.cmake:[0-9]+ \(cmake_path\): + Error after keyword "OUTPUT_VARIABLE": + + empty string not allowed diff --git a/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt index e1d6592..63289ef 100644 --- a/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt +++ b/Tests/RunCMake/cmake_path/OUTPUT_VARIABLE-no-arg-stderr.txt @@ -1,2 +1,4 @@ CMake Error at .+/cmake_path/call-cmake_path.cmake:[0-9]+ \(cmake_path\): - cmake_path OUTPUT_VARIABLE requires an argument. + Error after keyword "OUTPUT_VARIABLE": + + missing required value diff --git a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake index 991f46b..1742b06 100644 --- a/Tests/RunCMake/cmake_path/RunCMakeTest.cmake +++ b/Tests/RunCMake/cmake_path/RunCMakeTest.cmake @@ -74,6 +74,14 @@ foreach (command IN ITEMS APPEND APPEND_STRING REMOVE_FILENAME REPLACE_FILENAME endforeach() +## BASE_DIRECTORY without argument +set (RunCMake-stderr-file "BASE_DIRECTORY-no-arg-stderr.txt") + +foreach (command IN ITEMS RELATIVE_PATH ABSOLUTE_PATH) + run_cmake_command (${command}-OUTPUT_VARIABLE-no-arg "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path BASE_DIRECTORY" -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake") +endforeach() + + ## Invalid output variable set (RunCMake-stderr-file "invalid-output-var-stderr.txt") @@ -106,6 +114,9 @@ foreach (command IN ITEMS NATIVE_PATH run_cmake_command (${command}-invalid-output "${CMAKE_COMMAND}" "-DCMAKE_PATH_ARGUMENTS=${command} path ${extra_args}" -DCHECK_INVALID_OUTPUT=ON -P "${RunCMake_SOURCE_DIR}/call-cmake_path.cmake") endforeach() +# OUTPUT_VARIABLE empty name +set (RunCMake-stderr-file "OUTPUT_VARIABLE-empty-stderr.txt") + foreach (command IN ITEMS APPEND APPEND_STRING REMOVE_FILENAME REPLACE_FILENAME REMOVE_EXTENSION REPLACE_EXTENSION NORMAL_PATH RELATIVE_PATH ABSOLUTE_PATH) diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-stdout.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-stdout.txt new file mode 100644 index 0000000..a7eae05 --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop-stdout.txt @@ -0,0 +1 @@ +CTEST_TEST_VAR=set-via-ENVIRONMENT-property diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop.cmake new file mode 100644 index 0000000..51e7f2a --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-prop.cmake @@ -0,0 +1,9 @@ +include(CTest) + +add_test(NAME cmake_environment COMMAND "${CMAKE_COMMAND}" -E environment) +set_tests_properties( + cmake_environment + PROPERTIES + ENVIRONMENT "CTEST_TEST_VAR=set-via-ENVIRONMENT-property" + ENVIRONMENT_MODIFICATION "CTEST_TEST_VAR=set:set-via-ENVIRONMENT_MODIFICATION;CTEST_TEST_VAR=reset:" +) diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-result.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-stdout.txt b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-stdout.txt new file mode 100644 index 0000000..beaf133 --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system-stdout.txt @@ -0,0 +1 @@ +CTEST_TEST_VAR=set-via-system-environment diff --git a/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system.cmake b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system.cmake new file mode 100644 index 0000000..23268aa --- /dev/null +++ b/Tests/RunCMake/ctest_environment/ENVIRONMENT_MODIFICATION-reset-to-system.cmake @@ -0,0 +1,9 @@ +include(CTest) + +add_test(NAME cmake_environment COMMAND "${CMAKE_COMMAND}" -E environment) +set_tests_properties( + cmake_environment + PROPERTIES + # ENVIRONMENT "CTEST_TEST_VAR=set-via-ENVIRONMENT-property" + ENVIRONMENT_MODIFICATION "CTEST_TEST_VAR=set:set-via-ENVIRONMENT_MODIFICATION;CTEST_TEST_VAR=reset:" +) diff --git a/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake b/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake index 3447779..365c9e8 100644 --- a/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake +++ b/Tests/RunCMake/ctest_environment/RunCMakeTest.cmake @@ -10,3 +10,7 @@ set(RunCTest_VERBOSE_FLAG "-VV") run_ctest(ENVIRONMENT_MODIFICATION-invalid-op) run_ctest(ENVIRONMENT_MODIFICATION-no-colon) run_ctest(ENVIRONMENT_MODIFICATION-no-equals) + +set(ENV{CTEST_TEST_VAR} set-via-system-environment) +run_ctest(ENVIRONMENT_MODIFICATION-reset-to-prop) +run_ctest(ENVIRONMENT_MODIFICATION-reset-to-system) diff --git a/Tests/RunCMake/ctest_memcheck/testCudaSanitizer.cmake b/Tests/RunCMake/ctest_memcheck/testCudaSanitizer.cmake index adc7a1a..850f72c 100644 --- a/Tests/RunCMake/ctest_memcheck/testCudaSanitizer.cmake +++ b/Tests/RunCMake/ctest_memcheck/testCudaSanitizer.cmake @@ -277,3 +277,12 @@ file(APPEND "${LOG_FILE}" ========= ========= RACECHECK SUMMARY: 12 hazards displayed (0 errors, 12 warnings) ") + +# false-positives +file(APPEND "${LOG_FILE}" +"========= COMPUTE-SANITIZER +========= Error: Target application terminated before first instrumented API call +========= Tracking kernels launched by child processes requires the --target-processes all option. +========= Error: No attachable process found. compute-sanitizer timed-out. +========= Default timeout can be adjusted with --launch-timeout. Awaiting target completion. +") diff --git a/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt b/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt index e27f1e6..62cad52 100644 --- a/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt +++ b/Tests/RunCMake/execute_process/EchoCommand3-stderr.txt @@ -1,2 +1,4 @@ CMake Error at .*EchoCommand.cmake:.*\(execute_process\): - execute_process called with no value for COMMAND_ECHO. + Error after keyword "COMMAND_ECHO": + + missing required value diff --git a/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt b/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt index 1a69579..7f85654 100644 --- a/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt +++ b/Tests/RunCMake/execute_process/EncodingMissing-stderr.txt @@ -1,4 +1,7 @@ ^CMake Error at EncodingMissing.cmake:[0-9]+ \(execute_process\): - execute_process called with no value for ENCODING. + Error after keyword "ENCODING": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt deleted file mode 100644 index b22387b..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms-stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -CMake Error at CHMOD-all-perms\.cmake:[0-9]+ \(file\): - file Remove either PERMISSIONS or FILE_PERMISSIONS or DIRECTORY_PERMISSIONS - from the invocation -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake deleted file mode 100644 index b49583d..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-all-perms.cmake +++ /dev/null @@ -1,6 +0,0 @@ -file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) - -file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a) -file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_READ - FILE_PERMISSIONS OWNER_READ DIRECTORY_PERMISSIONS OWNER_READ) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt deleted file mode 100644 index 8d09e35..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path-stderr.txt +++ /dev/null @@ -1,6 +0,0 @@ -CMake Error at CHMOD-invalid-path\.cmake:[0-9]+ \(file\): - file does not exist: - - .*/chmod-tests/I_dont_exist -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake deleted file mode 100644 index 36915c1..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-path.cmake +++ /dev/null @@ -1,4 +0,0 @@ -file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) - -file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/I_dont_exist PERMISSIONS OWNER_READ) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt deleted file mode 100644 index 84ba2a2..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms-stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -CMake Error at CHMOD-invalid-perms\.cmake:[0-9]+ \(file\): - file INVALID_PERMISSION is an invalid permission specifier -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake deleted file mode 100644 index 22cab0b..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-invalid-perms.cmake +++ /dev/null @@ -1,5 +0,0 @@ -file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) - -file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a) -file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS INVALID_PERMISSION) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt deleted file mode 100644 index 2c248f8..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword-stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -CMake Error at CHMOD-no-keyword\.cmake:[0-9]+ \(file\): - file No permissions given -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake deleted file mode 100644 index 8b62106..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-no-keyword.cmake +++ /dev/null @@ -1,5 +0,0 @@ -file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) - -file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a) -file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt deleted file mode 100644 index a18609f..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms-stderr.txt +++ /dev/null @@ -1,4 +0,0 @@ -CMake Error at CHMOD-no-perms\.cmake:[0-9]+ \(file\): - file No permissions given -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake deleted file mode 100644 index 9fbd359..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-no-perms.cmake +++ /dev/null @@ -1,5 +0,0 @@ -file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) - -file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a) -file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake deleted file mode 100644 index 87e3e57..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-ok.cmake +++ /dev/null @@ -1,5 +0,0 @@ -file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) - -file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a) -file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_READ) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-override.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-override.cmake deleted file mode 100644 index d9226b8..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-override.cmake +++ /dev/null @@ -1,6 +0,0 @@ -file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) - -file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a) -file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_READ - FILE_PERMISSIONS OWNER_READ OWNER_WRITE) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt b/Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt deleted file mode 100644 index 1c87a59..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-write-only-stderr.txt +++ /dev/null @@ -1,6 +0,0 @@ -CMake Error at CHMOD-write-only\.cmake:[0-9]+ \(file\): - file failed to open for reading \(Permission denied\): - - .*/chmod-tests/a -Call Stack \(most recent call first\): - CMakeLists\.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake b/Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake deleted file mode 100644 index 1289efc..0000000 --- a/Tests/RunCMake/file-CHMOD/CHMOD-write-only.cmake +++ /dev/null @@ -1,6 +0,0 @@ -file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) -file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests) - -file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a "CONTENT") -file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a PERMISSIONS OWNER_WRITE) -file(READ ${CMAKE_CURRENT_BINARY_DIR}/chmod-tests/a content) diff --git a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake index 18deb89..e6b1169 100644 --- a/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake +++ b/Tests/RunCMake/file-CHMOD/RunCMakeTest.cmake @@ -1,12 +1,14 @@ include(RunCMake) -run_cmake(CHMOD-no-perms) -run_cmake(CHMOD-no-keyword) -run_cmake(CHMOD-all-perms) -run_cmake(CHMOD-invalid-perms) -run_cmake(CHMOD-invalid-path) -run_cmake(CHMOD-ok) -run_cmake(CHMOD-override) +run_cmake_script(no-perms) +run_cmake_script(missing-perms) +run_cmake_script(missing-file-perms) +run_cmake_script(missing-dir-perms) +run_cmake_script(all-perms) +run_cmake_script(invalid-perms) +run_cmake_script(invalid-path) +run_cmake_script(ok) +run_cmake_script(override) if(UNIX) execute_process(COMMAND id -u $ENV{USER} @@ -15,5 +17,5 @@ if(UNIX) endif() if(NOT WIN32 AND NOT MSYS AND NOT "${uid}" STREQUAL "0") - run_cmake(CHMOD-write-only) + run_cmake_script(write-only) endif() diff --git a/Tests/RunCMake/file-CHMOD/all-perms-result.txt b/Tests/RunCMake/file-CHMOD/all-perms-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/all-perms-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-CHMOD/all-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/all-perms-stderr.txt new file mode 100644 index 0000000..6932a1f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/all-perms-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at [^ +]*/all-perms\.cmake:[0-9]+ \(file\): + file Remove either PERMISSIONS or FILE_PERMISSIONS or DIRECTORY_PERMISSIONS + from the invocation$ diff --git a/Tests/RunCMake/file-CHMOD/all-perms.cmake b/Tests/RunCMake/file-CHMOD/all-perms.cmake new file mode 100644 index 0000000..5ff81b8 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/all-perms.cmake @@ -0,0 +1,3 @@ +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a) +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ + FILE_PERMISSIONS OWNER_READ DIRECTORY_PERMISSIONS OWNER_READ) diff --git a/Tests/RunCMake/file-CHMOD/invalid-path-result.txt b/Tests/RunCMake/file-CHMOD/invalid-path-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/invalid-path-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt b/Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt new file mode 100644 index 0000000..eb5fb31 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/invalid-path-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at [^ +]*/invalid-path\.cmake:[0-9]+ \(file\): + file does not exist: + + [^ +]*/Tests/RunCMake/file-CHMOD/invalid-path-build/I_dont_exist$ diff --git a/Tests/RunCMake/file-CHMOD/invalid-path.cmake b/Tests/RunCMake/file-CHMOD/invalid-path.cmake new file mode 100644 index 0000000..e8b0313 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/invalid-path.cmake @@ -0,0 +1 @@ +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/I_dont_exist PERMISSIONS OWNER_READ) diff --git a/Tests/RunCMake/file-CHMOD/invalid-perms-result.txt b/Tests/RunCMake/file-CHMOD/invalid-perms-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/invalid-perms-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt new file mode 100644 index 0000000..daab22e --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/invalid-perms-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at [^ +]*/invalid-perms\.cmake:[0-9]+ \(file\): + file INVALID_PERMISSION is an invalid permission specifier$ diff --git a/Tests/RunCMake/file-CHMOD/invalid-perms.cmake b/Tests/RunCMake/file-CHMOD/invalid-perms.cmake new file mode 100644 index 0000000..42129b9 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/invalid-perms.cmake @@ -0,0 +1,2 @@ +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a) +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS INVALID_PERMISSION) diff --git a/Tests/RunCMake/file-CHMOD/missing-dir-perms-result.txt b/Tests/RunCMake/file-CHMOD/missing-dir-perms-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/missing-dir-perms-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt new file mode 100644 index 0000000..c05bb2d --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/missing-dir-perms-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at [^ +]*/missing-dir-perms.cmake:[0-9]+ \(file\): + Error after keyword "DIRECTORY_PERMISSIONS": + + missing required value$ diff --git a/Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake b/Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake new file mode 100644 index 0000000..9d0fdad --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/missing-dir-perms.cmake @@ -0,0 +1,2 @@ +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a) +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ DIRECTORY_PERMISSIONS) diff --git a/Tests/RunCMake/file-CHMOD/missing-file-perms-result.txt b/Tests/RunCMake/file-CHMOD/missing-file-perms-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/missing-file-perms-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt new file mode 100644 index 0000000..c3f4f0f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/missing-file-perms-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at [^ +]*/missing-file-perms.cmake:[0-9]+ \(file\): + Error after keyword "FILE_PERMISSIONS": + + missing required value$ diff --git a/Tests/RunCMake/file-CHMOD/missing-file-perms.cmake b/Tests/RunCMake/file-CHMOD/missing-file-perms.cmake new file mode 100644 index 0000000..bcf35aa --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/missing-file-perms.cmake @@ -0,0 +1,2 @@ +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a) +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ FILE_PERMISSIONS) diff --git a/Tests/RunCMake/file-CHMOD/missing-perms-result.txt b/Tests/RunCMake/file-CHMOD/missing-perms-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/missing-perms-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt new file mode 100644 index 0000000..1508b13 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/missing-perms-stderr.txt @@ -0,0 +1,5 @@ +^CMake Error at [^ +]*/missing-perms.cmake:[0-9]+ \(file\): + Error after keyword "PERMISSIONS": + + missing required value$ diff --git a/Tests/RunCMake/file-CHMOD/missing-perms.cmake b/Tests/RunCMake/file-CHMOD/missing-perms.cmake new file mode 100644 index 0000000..da9f182 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/missing-perms.cmake @@ -0,0 +1,2 @@ +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a) +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a FILE_PERMISSIONS OWNER_READ PERMISSIONS) diff --git a/Tests/RunCMake/file-CHMOD/no-perms-result.txt b/Tests/RunCMake/file-CHMOD/no-perms-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/no-perms-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-CHMOD/no-perms-stderr.txt b/Tests/RunCMake/file-CHMOD/no-perms-stderr.txt new file mode 100644 index 0000000..4c5a139 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/no-perms-stderr.txt @@ -0,0 +1,3 @@ +^CMake Error at [^ +]*/no-perms\.cmake:[0-9]+ \(file\): + file No permissions given$ diff --git a/Tests/RunCMake/file-CHMOD/no-perms.cmake b/Tests/RunCMake/file-CHMOD/no-perms.cmake new file mode 100644 index 0000000..602cfc2 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/no-perms.cmake @@ -0,0 +1,2 @@ +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a) +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a) diff --git a/Tests/RunCMake/file-CHMOD/ok.cmake b/Tests/RunCMake/file-CHMOD/ok.cmake new file mode 100644 index 0000000..7c74d27 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/ok.cmake @@ -0,0 +1,2 @@ +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a) +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ) diff --git a/Tests/RunCMake/file-CHMOD/override.cmake b/Tests/RunCMake/file-CHMOD/override.cmake new file mode 100644 index 0000000..67e5a23 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/override.cmake @@ -0,0 +1,3 @@ +file(TOUCH ${CMAKE_CURRENT_BINARY_DIR}/a) +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_READ + FILE_PERMISSIONS OWNER_READ OWNER_WRITE) diff --git a/Tests/RunCMake/file-CHMOD/write-only-result.txt b/Tests/RunCMake/file-CHMOD/write-only-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/write-only-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/file-CHMOD/write-only-stderr.txt b/Tests/RunCMake/file-CHMOD/write-only-stderr.txt new file mode 100644 index 0000000..169a092 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/write-only-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at [^ +]*/write-only\.cmake:[0-9]+ \(file\): + file failed to open for reading \(Permission denied\): + + [^ +]*/Tests/RunCMake/file-CHMOD/write-only-build/a$ diff --git a/Tests/RunCMake/file-CHMOD/write-only.cmake b/Tests/RunCMake/file-CHMOD/write-only.cmake new file mode 100644 index 0000000..aa9d803 --- /dev/null +++ b/Tests/RunCMake/file-CHMOD/write-only.cmake @@ -0,0 +1,3 @@ +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/a "CONTENT") +file(CHMOD ${CMAKE_CURRENT_BINARY_DIR}/a PERMISSIONS OWNER_WRITE) +file(READ ${CMAKE_CURRENT_BINARY_DIR}/a content) diff --git a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt index c6ad3d0..39f307d 100644 --- a/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt +++ b/Tests/RunCMake/file-GET_RUNTIME_DEPENDENCIES/badargs2-stderr.txt @@ -13,11 +13,21 @@ Call Stack \(most recent call first\): This warning is for project developers\. Use -Wno-dev to suppress it\. CMake Error at badargs2\.cmake:[0-9]+ \(file\): - file Keywords missing values: + Error after keyword "BUNDLE_EXECUTABLE": + + missing required value + + Error after keyword "CONFLICTING_DEPENDENCIES_PREFIX": + + missing required value + + Error after keyword "RESOLVED_DEPENDENCIES_VAR": + + missing required value + + Error after keyword "UNRESOLVED_DEPENDENCIES_VAR": + + missing required value - RESOLVED_DEPENDENCIES_VAR - UNRESOLVED_DEPENDENCIES_VAR - CONFLICTING_DEPENDENCIES_PREFIX - BUNDLE_EXECUTABLE Call Stack \(most recent call first\): CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt b/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt index 7c58aeb..54a3e5a 100644 --- a/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt +++ b/Tests/RunCMake/file/REAL_PATH-no-base-dir-stderr.txt @@ -1,2 +1,7 @@ -CMake Error at REAL_PATH-no-base-dir.cmake:[0-9]+ \(file\): - file BASE_DIRECTORY requires a value +^CMake Error at REAL_PATH-no-base-dir.cmake:[0-9]+ \(file\): + Error after keyword "BASE_DIRECTORY": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/file/RunCMakeTest.cmake b/Tests/RunCMake/file/RunCMakeTest.cmake index aff4735..db88956 100644 --- a/Tests/RunCMake/file/RunCMakeTest.cmake +++ b/Tests/RunCMake/file/RunCMakeTest.cmake @@ -47,6 +47,7 @@ run_cmake(GLOB_RECURSE) run_cmake(GLOB_RECURSE-noexp-FOLLOW_SYMLINKS) run_cmake(SIZE) run_cmake(SIZE-error-does-not-exist) +run_cmake(TIMESTAMP) run_cmake(REMOVE-empty) diff --git a/Tests/RunCMake/file/TIMESTAMP-stdout.txt b/Tests/RunCMake/file/TIMESTAMP-stdout.txt new file mode 100644 index 0000000..42be6ba --- /dev/null +++ b/Tests/RunCMake/file/TIMESTAMP-stdout.txt @@ -0,0 +1 @@ +-- '[0-9]*-[01][0-9]-[0-3][0-9]T[0-2][0-9]:[0-5][0-9]:[0-6][0-9]Z' diff --git a/Tests/RunCMake/file/TIMESTAMP.cmake b/Tests/RunCMake/file/TIMESTAMP.cmake new file mode 100644 index 0000000..2bd2577 --- /dev/null +++ b/Tests/RunCMake/file/TIMESTAMP.cmake @@ -0,0 +1,2 @@ +file(TIMESTAMP "TIMESTAMP.cmake" output UTC) +message(STATUS "'${output}'") diff --git a/Tests/RunCMake/find_file/RunCMakeTest.cmake b/Tests/RunCMake/find_file/RunCMakeTest.cmake index 23765d4..296bb71 100644 --- a/Tests/RunCMake/find_file/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_file/RunCMakeTest.cmake @@ -7,6 +7,10 @@ run_cmake(Required) run_cmake(NO_CACHE) run_cmake(REGISTRY_VIEW-no-view) run_cmake(REGISTRY_VIEW-wrong-view) +run_cmake(VALIDATOR-no-function) +run_cmake(VALIDATOR-undefined-function) +run_cmake(VALIDATOR-specify-macro) +run_cmake(VALIDATOR) run_cmake_with_options(FromPATHEnvDebugVar --debug-find-var=PrefixInPATH_File) diff --git a/Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-no-function-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt new file mode 100644 index 0000000..4d49649 --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-no-function-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_file\): + find_file missing required argument for "VALIDATOR" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_file/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_file/VALIDATOR-no-function.cmake new file mode 100644 index 0000000..4800fe9 --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-no-function.cmake @@ -0,0 +1,2 @@ + +find_file(result NAMES input.txt VALIDATOR) diff --git a/Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt new file mode 100644 index 0000000..7e0eda0 --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-specify-macro-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_file\): + find_file command specified for "VALIDATOR" is not a function: check. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake new file mode 100644 index 0000000..ec0ce9a --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-specify-macro.cmake @@ -0,0 +1,5 @@ + +macro(CHECK result path) +endmacro() + +find_file(result NAMES input.txt VALIDATOR check) diff --git a/Tests/RunCMake/find_file/VALIDATOR-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-stderr.txt new file mode 100644 index 0000000..6c8159b --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-stderr.txt @@ -0,0 +1,3 @@ +CHECK='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h' +CHECK='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h' +CHECK='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h' diff --git a/Tests/RunCMake/find_file/VALIDATOR-stdout.txt b/Tests/RunCMake/find_file/VALIDATOR-stdout.txt new file mode 100644 index 0000000..44fa77c --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-stdout.txt @@ -0,0 +1,3 @@ +-- FILE='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- FILE='[^']+/Tests/RunCMake/find_file/include/PrefixInPATH.h' +-- FILE='FILE-NOTFOUND' diff --git a/Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt new file mode 100644 index 0000000..b4125e6 --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-undefined-function-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_file\): + find_file command specified for "VALIDATOR" is undefined: undefined. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake new file mode 100644 index 0000000..c465887 --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR-undefined-function.cmake @@ -0,0 +1,2 @@ + +find_file(result NAMES input.txt VALIDATOR undefined) diff --git a/Tests/RunCMake/find_file/VALIDATOR.cmake b/Tests/RunCMake/find_file/VALIDATOR.cmake new file mode 100644 index 0000000..72dd8f9 --- /dev/null +++ b/Tests/RunCMake/find_file/VALIDATOR.cmake @@ -0,0 +1,39 @@ + +function(CHECK_DEFAULT result filename) + message("CHECK='${filename}'") +endfunction() + +function(CHECK_OK result filename) + message("CHECK='${filename}'") + set(${result} TRUE PARENT_SCOPE) +endfunction() + +function(CHECK_KO result filename) + message("CHECK='${filename}'") + set(${result} FALSE PARENT_SCOPE) +endfunction() + + +find_file(FILE + NAMES PrefixInPATH.h + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include + VALIDATOR check_default + ) +message(STATUS "FILE='${FILE}'") +unset(FILE CACHE) + +find_file(FILE + NAMES PrefixInPATH.h + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include + VALIDATOR check_ok + ) +message(STATUS "FILE='${FILE}'") +unset(FILE CACHE) + +find_file(FILE + NAMES PrefixInPATH.h + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include + VALIDATOR check_ko + ) +message(STATUS "FILE='${FILE}'") +unset(FILE CACHE) diff --git a/Tests/RunCMake/find_library/RunCMakeTest.cmake b/Tests/RunCMake/find_library/RunCMakeTest.cmake index a912077..8b223b4 100644 --- a/Tests/RunCMake/find_library/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_library/RunCMakeTest.cmake @@ -15,6 +15,10 @@ run_cmake(Required) run_cmake(NO_CACHE) run_cmake(REGISTRY_VIEW-no-view) run_cmake(REGISTRY_VIEW-wrong-view) +run_cmake(VALIDATOR-no-function) +run_cmake(VALIDATOR-undefined-function) +run_cmake(VALIDATOR-specify-macro) +run_cmake(VALIDATOR) run_cmake_script(FromScriptMode "-DTEMP_DIR=${RunCMake_BINARY_DIR}/FromScriptMode-temp") diff --git a/Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-no-function-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt new file mode 100644 index 0000000..6c04aa4 --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-no-function-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_library\): + find_library missing required argument for "VALIDATOR" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_library/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_library/VALIDATOR-no-function.cmake new file mode 100644 index 0000000..516e54e --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-no-function.cmake @@ -0,0 +1,2 @@ + +find_library(result NAMES input.txt VALIDATOR) diff --git a/Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt new file mode 100644 index 0000000..03e7df9 --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-specify-macro-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_library\): + find_library command specified for "VALIDATOR" is not a function: check. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake new file mode 100644 index 0000000..fa90d72 --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-specify-macro.cmake @@ -0,0 +1,5 @@ + +macro(CHECK result path) +endmacro() + +find_library(result NAMES input.txt VALIDATOR check) diff --git a/Tests/RunCMake/find_library/VALIDATOR-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-stderr.txt new file mode 100644 index 0000000..7211450 --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-stderr.txt @@ -0,0 +1,3 @@ +CHECK='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +CHECK='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +CHECK='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' diff --git a/Tests/RunCMake/find_library/VALIDATOR-stdout.txt b/Tests/RunCMake/find_library/VALIDATOR-stdout.txt new file mode 100644 index 0000000..bd2549b --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-stdout.txt @@ -0,0 +1,3 @@ +-- LIB='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- LIB='[^']+/Tests/RunCMake/find_library/lib/libPrefixInPATH.a' +-- LIB='LIB-NOTFOUND' diff --git a/Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt new file mode 100644 index 0000000..dc7ad9e --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-undefined-function-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_library\): + find_library command specified for "VALIDATOR" is undefined: undefined. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake new file mode 100644 index 0000000..9ac7ee0 --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR-undefined-function.cmake @@ -0,0 +1,2 @@ + +find_library(result NAMES input.txt VALIDATOR undefined) diff --git a/Tests/RunCMake/find_library/VALIDATOR.cmake b/Tests/RunCMake/find_library/VALIDATOR.cmake new file mode 100644 index 0000000..7593941 --- /dev/null +++ b/Tests/RunCMake/find_library/VALIDATOR.cmake @@ -0,0 +1,41 @@ +list(APPEND CMAKE_FIND_LIBRARY_PREFIXES lib) +list(APPEND CMAKE_FIND_LIBRARY_SUFFIXES .a) + +function(CHECK_DEFAULT result filename) + message("CHECK='${filename}'") +endfunction() + +function(CHECK_OK result filename) + message("CHECK='${filename}'") + set(${result} TRUE PARENT_SCOPE) +endfunction() + +function(CHECK_KO result filename) + message("CHECK='${filename}'") + set(${result} FALSE PARENT_SCOPE) +endfunction() + + +find_library(LIB + NAMES PrefixInPATH + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/lib + VALIDATOR check_default + ) +message(STATUS "LIB='${LIB}'") +unset(LIB CACHE) + +find_library(LIB + NAMES PrefixInPATH + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/lib + VALIDATOR check_ok + ) +message(STATUS "LIB='${LIB}'") +unset(LIB CACHE) + +find_library(LIB + NAMES PrefixInPATH + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/lib + VALIDATOR check_ko + ) +message(STATUS "LIB='${LIB}'") +unset(LIB CACHE) diff --git a/Tests/RunCMake/find_package/RunCMakeTest.cmake b/Tests/RunCMake/find_package/RunCMakeTest.cmake index 32e54d5..fa41fc1 100644 --- a/Tests/RunCMake/find_package/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_package/RunCMakeTest.cmake @@ -55,6 +55,22 @@ run_cmake(REGISTRY_VIEW-no-view) run_cmake(REGISTRY_VIEW-wrong-view) run_cmake(REGISTRY_VIEW-propagated) +file( + GLOB SearchPaths_TEST_CASE_LIST + LIST_DIRECTORIES TRUE + "${RunCMake_SOURCE_DIR}/SearchPaths/*" + ) +foreach(TestCasePrefix IN LISTS SearchPaths_TEST_CASE_LIST) + if(IS_DIRECTORY "${TestCasePrefix}") + cmake_path(GET TestCasePrefix FILENAME TestSuffix) + run_cmake_with_options( + SearchPaths_${TestSuffix} + "-DSearchPaths_ROOT=${TestCasePrefix}" + "--debug-find-pkg=SearchPaths" + ) + endif() +endforeach() + if(UNIX AND NOT MSYS # FIXME: This works on CYGWIN but not on MSYS ) diff --git a/Tests/RunCMake/find_package/SearchPaths.cmake b/Tests/RunCMake/find_package/SearchPaths.cmake new file mode 100644 index 0000000..a5a10fc --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths.cmake @@ -0,0 +1,2 @@ +cmake_policy(SET CMP0074 NEW) +find_package(SearchPaths REQUIRED CONFIG) diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1.2.3/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1.2.3/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1.2.3/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1.2.3/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1.2.3/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1.2.3/lib/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1.2.3/lib/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1.2.3/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1.2.3/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1.2.3/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1.2.3/share/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1.2.3/share/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1.2.3/share/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1.2.3/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1.2.3/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1.2.3/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1.2.3/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1.2.3/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1.2.3/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake b/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1.2.3/cmake/SearchPathsConfig.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix-stderr.txt new file mode 100644 index 0000000..fae13ef --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix-stderr.txt @@ -0,0 +1,10 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-stderr.txt new file mode 100644 index 0000000..eba88c9 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-stderr.txt @@ -0,0 +1,12 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_cmake/cmake/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_cmake.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_cmake.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-stderr.txt new file mode 100644 index 0000000..cebc169 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-stderr.txt @@ -0,0 +1,12 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_cmake_pkg/lib/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_cmake_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-stderr.txt new file mode 100644 index 0000000..4e5d3f6 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-stderr.txt @@ -0,0 +1,12 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg/lib/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-stderr.txt new file mode 100644 index 0000000..f290545 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-stderr.txt @@ -0,0 +1,12 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_lib_pkg_cmake/lib/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_lib_pkg_cmake.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-stderr.txt new file mode 100644 index 0000000..32b9fcb --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-stderr.txt @@ -0,0 +1,12 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-stderr.txt new file mode 100644 index 0000000..7bf5cf8 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-stderr.txt @@ -0,0 +1,14 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1\.2\.3/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-stderr.txt new file mode 100644 index 0000000..812c607 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-stderr.txt @@ -0,0 +1,14 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1\.2\.3/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_cmake_pkg/SearchPaths-1\.2\.3/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_cmake_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-stderr.txt new file mode 100644 index 0000000..3592f72 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-stderr.txt @@ -0,0 +1,14 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1\.2\.3/lib/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_cmake_pkg/SearchPaths-1\.2\.3/lib/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_cmake_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-stderr.txt new file mode 100644 index 0000000..b196b7a --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-stderr.txt @@ -0,0 +1,14 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1\.2\.3/lib/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg/SearchPaths-1\.2\.3/lib/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-stderr.txt new file mode 100644 index 0000000..17e0399 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-stderr.txt @@ -0,0 +1,14 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1\.2\.3/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1\.2\.3/lib/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_lib_pkg_cmake/SearchPaths-1\.2\.3/lib/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_lib_pkg_cmake.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-stderr.txt new file mode 100644 index 0000000..ee01a50 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-stderr.txt @@ -0,0 +1,14 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1\.2\.3/share/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_cmake_pkg/SearchPaths-1\.2\.3/share/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_cmake_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-stderr.txt new file mode 100644 index 0000000..d6abd2f --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-stderr.txt @@ -0,0 +1,14 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1\.2\.3/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1\.2\.3/share/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg/SearchPaths-1\.2\.3/share/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-stderr.txt new file mode 100644 index 0000000..b578b2b --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-stderr.txt @@ -0,0 +1,14 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1\.2\.3/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1\.2\.3/share/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_pkg_share_pkg_cmake/SearchPaths-1\.2\.3/share/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_pkg_share_pkg_cmake.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-stderr.txt new file mode 100644 index 0000000..2f3f18a --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-stderr.txt @@ -0,0 +1,12 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_cmake_pkg/share/cmake/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_cmake_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-stderr.txt new file mode 100644 index 0000000..3eef002 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-stderr.txt @@ -0,0 +1,12 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg/share/SearchPaths-1\.2\.3/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-stderr.txt b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-stderr.txt new file mode 100644 index 0000000..c962f8b --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-stderr.txt @@ -0,0 +1,12 @@ + find_package considered the following locations for SearchPaths's Config + module: + + .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-build/CMakeFiles/pkgRedirects/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake-build/CMakeFiles/pkgRedirects/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/SearchPathsConfig\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/searchpaths-config\.cmake + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake + + The file was found at + + .*/Tests/RunCMake/find_package/SearchPaths/prefix_share_pkg_cmake/share/SearchPaths-1\.2\.3/cmake/SearchPathsConfig\.cmake diff --git a/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake.cmake b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake.cmake new file mode 100644 index 0000000..d831313 --- /dev/null +++ b/Tests/RunCMake/find_package/SearchPaths_prefix_share_pkg_cmake.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_SOURCE_DIR}/SearchPaths.cmake") diff --git a/Tests/RunCMake/find_path/RunCMakeTest.cmake b/Tests/RunCMake/find_path/RunCMakeTest.cmake index 63cadc2..9c76f2e 100644 --- a/Tests/RunCMake/find_path/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_path/RunCMakeTest.cmake @@ -7,6 +7,10 @@ run_cmake(Required) run_cmake(NO_CACHE) run_cmake(REGISTRY_VIEW-no-view) run_cmake(REGISTRY_VIEW-wrong-view) +run_cmake(VALIDATOR-no-function) +run_cmake(VALIDATOR-undefined-function) +run_cmake(VALIDATOR-specify-macro) +run_cmake(VALIDATOR) if(APPLE) run_cmake(FrameworksWithSubdirs) diff --git a/Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-no-function-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt new file mode 100644 index 0000000..1dfd064 --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-no-function-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_path\): + find_path missing required argument for "VALIDATOR" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_path/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_path/VALIDATOR-no-function.cmake new file mode 100644 index 0000000..bac2752 --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-no-function.cmake @@ -0,0 +1,2 @@ + +find_path(result NAMES input.txt VALIDATOR) diff --git a/Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt new file mode 100644 index 0000000..92ee17e --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-specify-macro-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_path\): + find_path command specified for "VALIDATOR" is not a function: check. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake new file mode 100644 index 0000000..62b44ed --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-specify-macro.cmake @@ -0,0 +1,5 @@ + +macro(CHECK result path) +endmacro() + +find_path(result NAMES input.txt VALIDATOR check) diff --git a/Tests/RunCMake/find_path/VALIDATOR-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-stderr.txt new file mode 100644 index 0000000..851353d --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-stderr.txt @@ -0,0 +1,3 @@ +CHECK='[^']+/Tests/RunCMake/find_path/include/' +CHECK='[^']+/Tests/RunCMake/find_path/include/' +CHECK='[^']+/Tests/RunCMake/find_path/include/' diff --git a/Tests/RunCMake/find_path/VALIDATOR-stdout.txt b/Tests/RunCMake/find_path/VALIDATOR-stdout.txt new file mode 100644 index 0000000..3fce030 --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-stdout.txt @@ -0,0 +1,3 @@ +-- DIR='[^']+/Tests/RunCMake/find_path/include' +-- DIR='[^']+/Tests/RunCMake/find_path/include' +-- DIR='DIR-NOTFOUND' diff --git a/Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt new file mode 100644 index 0000000..d3e0517 --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-undefined-function-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_path\): + find_path command specified for "VALIDATOR" is undefined: undefined. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake new file mode 100644 index 0000000..3fb55c5 --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR-undefined-function.cmake @@ -0,0 +1,2 @@ + +find_path(result NAMES input.txt VALIDATOR undefined) diff --git a/Tests/RunCMake/find_path/VALIDATOR.cmake b/Tests/RunCMake/find_path/VALIDATOR.cmake new file mode 100644 index 0000000..1e01250 --- /dev/null +++ b/Tests/RunCMake/find_path/VALIDATOR.cmake @@ -0,0 +1,39 @@ + +function(CHECK_DEFAULT result filename) + message("CHECK='${filename}'") +endfunction() + +function(CHECK_OK result filename) + message("CHECK='${filename}'") + set(${result} TRUE PARENT_SCOPE) +endfunction() + +function(CHECK_KO result filename) + message("CHECK='${filename}'") + set(${result} FALSE PARENT_SCOPE) +endfunction() + + +find_path(DIR + NAMES PrefixInPATH.h + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include + VALIDATOR check_default + ) +message(STATUS "DIR='${DIR}'") +unset(DIR CACHE) + +find_path(DIR + NAMES PrefixInPATH.h + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include + VALIDATOR check_ok + ) +message(STATUS "DIR='${DIR}'") +unset(DIR CACHE) + +find_path(DIR + NAMES PrefixInPATH.h + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/include + VALIDATOR check_ko + ) +message(STATUS "DIR='${DIR}'") +unset(DIR CACHE) diff --git a/Tests/RunCMake/find_program/RunCMakeTest.cmake b/Tests/RunCMake/find_program/RunCMakeTest.cmake index d0ce8fc..f8ecb8f 100644 --- a/Tests/RunCMake/find_program/RunCMakeTest.cmake +++ b/Tests/RunCMake/find_program/RunCMakeTest.cmake @@ -9,6 +9,10 @@ run_cmake(NO_CACHE) run_cmake(IgnorePrefixPath) run_cmake(REGISTRY_VIEW-no-view) run_cmake(REGISTRY_VIEW-wrong-view) +run_cmake(VALIDATOR-no-function) +run_cmake(VALIDATOR-undefined-function) +run_cmake(VALIDATOR-specify-macro) +run_cmake(VALIDATOR) if(CMAKE_SYSTEM_NAME MATCHES "^(Windows|CYGWIN|MSYS)$") run_cmake(WindowsCom) diff --git a/Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt b/Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-no-function-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt new file mode 100644 index 0000000..b8868af --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-no-function-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-no-function.cmake:[0-9]+ \(find_program\): + find_program missing required argument for "VALIDATOR" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_program/VALIDATOR-no-function.cmake b/Tests/RunCMake/find_program/VALIDATOR-no-function.cmake new file mode 100644 index 0000000..0d6a74f --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-no-function.cmake @@ -0,0 +1,2 @@ + +find_program(result NAMES input.txt VALIDATOR) diff --git a/Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt new file mode 100644 index 0000000..1ae5148 --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-specify-macro-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-specify-macro.cmake:[0-9]+ \(find_program\): + find_program command specified for "VALIDATOR" is not a function: check. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake b/Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake new file mode 100644 index 0000000..43bb9ec --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-specify-macro.cmake @@ -0,0 +1,5 @@ + +macro(CHECK result path) +endmacro() + +find_program(result NAMES input.txt VALIDATOR check) diff --git a/Tests/RunCMake/find_program/VALIDATOR-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-stderr.txt new file mode 100644 index 0000000..6704ed1 --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-stderr.txt @@ -0,0 +1,3 @@ +CHECK='[^']+/Tests/RunCMake/find_program/A/testA' +CHECK='[^']+/Tests/RunCMake/find_program/A/testA' +CHECK='[^']+/Tests/RunCMake/find_program/A/testA' diff --git a/Tests/RunCMake/find_program/VALIDATOR-stdout.txt b/Tests/RunCMake/find_program/VALIDATOR-stdout.txt new file mode 100644 index 0000000..d434742 --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-stdout.txt @@ -0,0 +1,3 @@ +-- PROG='[^']+/Tests/RunCMake/find_program/A/testA' +-- PROG='[^']+/Tests/RunCMake/find_program/A/testA' +-- PROG='PROG-NOTFOUND' diff --git a/Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt new file mode 100644 index 0000000..a89ffa0 --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-undefined-function-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at VALIDATOR-undefined-function.cmake:[0-9]+ \(find_program\): + find_program command specified for "VALIDATOR" is undefined: undefined. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake b/Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake new file mode 100644 index 0000000..96be5fd --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR-undefined-function.cmake @@ -0,0 +1,2 @@ + +find_program(result NAMES input.txt VALIDATOR undefined) diff --git a/Tests/RunCMake/find_program/VALIDATOR.cmake b/Tests/RunCMake/find_program/VALIDATOR.cmake new file mode 100644 index 0000000..8be2b39 --- /dev/null +++ b/Tests/RunCMake/find_program/VALIDATOR.cmake @@ -0,0 +1,39 @@ + +function(CHECK_DEFAULT result filename) + message("CHECK='${filename}'") +endfunction() + +function(CHECK_OK result filename) + message("CHECK='${filename}'") + set(${result} TRUE PARENT_SCOPE) +endfunction() + +function(CHECK_KO result filename) + message("CHECK='${filename}'") + set(${result} FALSE PARENT_SCOPE) +endfunction() + + +find_program(PROG + NAMES testA + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A + VALIDATOR check_default + ) +message(STATUS "PROG='${PROG}'") +unset(PROG CACHE) + +find_program(PROG + NAMES testA + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A + VALIDATOR check_ok + ) +message(STATUS "PROG='${PROG}'") +unset(PROG CACHE) + +find_program(PROG + NAMES testA + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/A + VALIDATOR check_ko + ) +message(STATUS "PROG='${PROG}'") +unset(PROG CACHE) diff --git a/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-result.txt b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stderr.txt b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stderr.txt new file mode 100644 index 0000000..d082b8a --- /dev/null +++ b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stderr.txt @@ -0,0 +1,12 @@ +^CMake Error at cmake_install.cmake:[0-9]+ \(file\): + file INSTALL cannot duplicate symlink + + [^ +]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/new/dir + + at + + [^ +]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/dir + + because: A directory already exists at that location diff --git a/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stdout.txt b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stdout.txt new file mode 100644 index 0000000..c520de1 --- /dev/null +++ b/Tests/RunCMake/install/DIRECTORY-symlink-clobber-all-stdout.txt @@ -0,0 +1,12 @@ +-- Installing: [^ +]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/dir +-- Installing: [^ +]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/dir/file +-- Installing: [^ +]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/lnk +-- Installing: [^ +]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/lnk +-- (Up-to-date|Installing): [^ +]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/lnk/file +-- Installing: [^ +]*/Tests/RunCMake/install/DIRECTORY-symlink-clobber-build/root-all/dest/dir diff --git a/Tests/RunCMake/install/DIRECTORY-symlink-clobber.cmake b/Tests/RunCMake/install/DIRECTORY-symlink-clobber.cmake new file mode 100644 index 0000000..ac7a2cf --- /dev/null +++ b/Tests/RunCMake/install/DIRECTORY-symlink-clobber.cmake @@ -0,0 +1,11 @@ +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/old/dir) +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/old/dir/file "") +file(CREATE_LINK dir ${CMAKE_CURRENT_BINARY_DIR}/old/lnk SYMBOLIC) +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/old/dir DESTINATION dest) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/old/lnk DESTINATION dest) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/new/lnk) +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/new/lnk/file "") +file(CREATE_LINK lnk ${CMAKE_CURRENT_BINARY_DIR}/new/dir SYMBOLIC) +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/new/lnk DESTINATION dest) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/new/dir DESTINATION dest) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index 7c12d4a..477ffe0 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -175,6 +175,10 @@ run_install_test(FILES-PERMISSIONS) run_install_test(TARGETS-RPATH) run_install_test(InstallRequiredSystemLibraries) +if(UNIX) + run_install_test(DIRECTORY-symlink-clobber) +endif() + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle) run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework) diff --git a/Tests/RunCMake/project/LanguagesDuplicate-check.cmake b/Tests/RunCMake/project/LanguagesDuplicate-check.cmake new file mode 100644 index 0000000..31c7da3 --- /dev/null +++ b/Tests/RunCMake/project/LanguagesDuplicate-check.cmake @@ -0,0 +1,10 @@ +if(NOT actual_stderr MATCHES "The following language has been specified multiple times: C\n") + set(RunCMake_TEST_FAILED "'LANGUAGES C C C' should report only 'C' and only once.") +endif() + +if(NOT actual_stderr MATCHES "The following languages have been specified multiple times: C, CXX\n") + if(RunCMake_TEST_FAILED) + string(APPEND RunCMake_TEST_FAILED "\n") + endif() + string(APPEND RunCMake_TEST_FAILED "'LANGUAGES C C CXX CXX' should report 'C' and 'CXX'.") +endif() diff --git a/Tests/RunCMake/project/LanguagesDuplicate.cmake b/Tests/RunCMake/project/LanguagesDuplicate.cmake new file mode 100644 index 0000000..97a79d0 --- /dev/null +++ b/Tests/RunCMake/project/LanguagesDuplicate.cmake @@ -0,0 +1,11 @@ +cmake_policy(SET CMP0057 NEW) + +project(ProjectA C C C) +project(ProjectB C C CXX CXX) + +get_property(langs GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(lang C CXX) + if(NOT lang IN_LIST langs) + message(FATAL_ERROR "Expected language '${lang}' to be enabled.") + endif() +endforeach() diff --git a/Tests/RunCMake/project/RunCMakeTest.cmake b/Tests/RunCMake/project/RunCMakeTest.cmake index 945d9ed..6d9f52f 100644 --- a/Tests/RunCMake/project/RunCMakeTest.cmake +++ b/Tests/RunCMake/project/RunCMakeTest.cmake @@ -12,6 +12,11 @@ run_cmake_with_options(CodeInjection if(CMake_TEST_RESOURCES) run_cmake(ExplicitRC) endif() + +set(RunCMake_DEFAULT_stderr .) +run_cmake(LanguagesDuplicate) +unset(RunCMake_DEFAULT_stderr) + run_cmake(LanguagesImplicit) run_cmake(LanguagesEmpty) run_cmake(LanguagesNONE) diff --git a/Tests/RunCMake/pseudo_tidy.c b/Tests/RunCMake/pseudo_tidy.c index 2feeb0f..a43133b 100644 --- a/Tests/RunCMake/pseudo_tidy.c +++ b/Tests/RunCMake/pseudo_tidy.c @@ -5,6 +5,16 @@ int main(int argc, char* argv[]) { int i; for (i = 1; i < argc; ++i) { + if (strcmp(argv[i], "-p") == 0) { + // Ensure compile commands were not appended after the source file + for (++i; i < argc; ++i) { + if (strcmp(argv[i], "--") == 0) { + fprintf(stderr, "Command line arguments unexpectedly appended\n"); + return 1; + } + } + return 0; + } if (strcmp(argv[i], "-bad") == 0) { fprintf(stdout, "stdout from bad command line arg '-bad'\n"); fprintf(stderr, "stderr from bad command line arg '-bad'\n"); diff --git a/Tests/RunCMake/return/CMP0140-NEW.cmake b/Tests/RunCMake/return/CMP0140-NEW.cmake new file mode 100644 index 0000000..eb6b85c --- /dev/null +++ b/Tests/RunCMake/return/CMP0140-NEW.cmake @@ -0,0 +1,13 @@ + +cmake_policy(SET CMP0140 NEW) + +function(FUNC) + set(VAR "set") + return(PROPAGATE VAR) +endfunction() + +set(VAR "initial") +func() +if (NOT DEFINED VAR OR NOT VAR STREQUAL "set") + message(FATAL_ERROR "return(PROPAGATE) not handled correctly.") +endif() diff --git a/Tests/RunCMake/return/CMP0140-OLD.cmake b/Tests/RunCMake/return/CMP0140-OLD.cmake new file mode 100644 index 0000000..8113a43 --- /dev/null +++ b/Tests/RunCMake/return/CMP0140-OLD.cmake @@ -0,0 +1,8 @@ + +cmake_policy(SET CMP0140 OLD) + +function(FUNC) + return(PROPAGATE VAR) +endfunction() + +func() diff --git a/Tests/RunCMake/return/CMP0140-WARN-result.txt b/Tests/RunCMake/return/CMP0140-WARN-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/return/CMP0140-WARN-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/return/CMP0140-WARN-stderr.txt b/Tests/RunCMake/return/CMP0140-WARN-stderr.txt new file mode 100644 index 0000000..ed4beb6 --- /dev/null +++ b/Tests/RunCMake/return/CMP0140-WARN-stderr.txt @@ -0,0 +1,12 @@ +CMake Warning \(dev\) at CMP0140-WARN.cmake:[0-9]+ \(return\): + Policy CMP0140 is not set: The return\(\) command checks its arguments. Run + "cmake --help-policy CMP0140" for policy details. Use the cmake_policy + command to set the policy and suppress this warning. + + return\(\) checks its arguments when the policy is set to NEW. Since the + policy is not set the OLD behavior will be used so the arguments will be + ignored. +Call Stack \(most recent call first\): + CMP0140-WARN.cmake:[0-9]+ \(func\) + CMakeLists.txt:[0-9]+ \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/return/CMP0140-WARN.cmake b/Tests/RunCMake/return/CMP0140-WARN.cmake new file mode 100644 index 0000000..df2fc88 --- /dev/null +++ b/Tests/RunCMake/return/CMP0140-WARN.cmake @@ -0,0 +1,8 @@ + +cmake_policy(VERSION 3.1) + +function(FUNC) + return(PROPAGATE VAR) +endfunction() + +func() diff --git a/Tests/RunCMake/return/CMakeLists.txt b/Tests/RunCMake/return/CMakeLists.txt index ef2163c..6cc903f 100644 --- a/Tests/RunCMake/return/CMakeLists.txt +++ b/Tests/RunCMake/return/CMakeLists.txt @@ -1,3 +1,3 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.1...3.25) project(${RunCMake_TEST} NONE) include(${RunCMake_TEST}.cmake) diff --git a/Tests/RunCMake/return/PropagateFromDirectory.cmake b/Tests/RunCMake/return/PropagateFromDirectory.cmake new file mode 100644 index 0000000..9c820bb --- /dev/null +++ b/Tests/RunCMake/return/PropagateFromDirectory.cmake @@ -0,0 +1,10 @@ + +set(VAR1 "initial") +set(VAR2 "initial") + +add_subdirectory(subdir) + +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for FUNC1") +endif() diff --git a/Tests/RunCMake/return/PropagateFromFunction.cmake b/Tests/RunCMake/return/PropagateFromFunction.cmake new file mode 100644 index 0000000..1c12bc1 --- /dev/null +++ b/Tests/RunCMake/return/PropagateFromFunction.cmake @@ -0,0 +1,142 @@ + +function(FUNC1) + set(VAR1 "set") + unset(VAR2) + return(PROPAGATE VAR1 VAR2) +endfunction() + +set(VAR1 "initial") +set(VAR2 "initial") +func1() +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for FUNC1") +endif() + + +function(FUNC2) + block() + set(VAR1 "set") + unset(VAR2) + return(PROPAGATE VAR1 VAR2) + endblock() +endfunction() + +set(VAR1 "initial") +set(VAR2 "initial") +func2() +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for FUNC2") +endif() + + +function(FUNC3) + block(SCOPE_FOR POLICIES) + set(VAR1 "set") + unset(VAR2) + return(PROPAGATE VAR1 VAR2) + endblock() +endfunction() + +set(VAR1 "initial") +set(VAR2 "initial") +func3() +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for FUNC3") +endif() + + +function(FUNC4) + while(TRUE) + set(VAR1 "set") + unset(VAR2) + return(PROPAGATE VAR1 VAR2) + endwhile() +endfunction() + +set(VAR1 "initial") +set(VAR2 "initial") +func4() +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for FUNC4") +endif() + + +function(FUNC5) + foreach(item IN ITEMS A B) + set(VAR1 "set") + unset(VAR2) + return(PROPAGATE VAR1 VAR2) + endforeach() +endfunction() + +set(VAR1 "initial") +set(VAR2 "initial") +func5() +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for FUNC5") +endif() + + +function(FUNC6) + if(TRUE) + set(VAR1 "set") + unset(VAR2) + return(PROPAGATE VAR1 VAR2) + endif() +endfunction() + +set(VAR1 "initial") +set(VAR2 "initial") +func6() +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for FUNC6") +endif() + + +function(FUNC7) + if(FALSE) + else() + set(VAR1 "set") + unset(VAR2) + return(PROPAGATE VAR1 VAR2) + endif() +endfunction() + +set(VAR1 "initial") +set(VAR2 "initial") +func7() +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for FUNC7") +endif() + + +set(VAR1 "initial") +set(VAR2 "initial") +cmake_language(CALL func7) +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for cmake_language(CALL FUNC7)") +endif() + + +set(VAR1 "initial") +set(VAR2 "initial") +cmake_language(EVAL CODE " + function(FUNC8) + set(VAR1 \"set\") + unset(VAR2) + return(PROPAGATE VAR1 VAR2) + endfunction() + + func8()") +if((NOT DEFINED VAR1 OR NOT VAR1 STREQUAL "set") + OR DEFINED VAR2) + message(SEND_ERROR "erroneous propagation for cmake_language(EVAL CODE)") +endif() diff --git a/Tests/RunCMake/return/PropagateNothing.cmake b/Tests/RunCMake/return/PropagateNothing.cmake new file mode 100644 index 0000000..0ace58e --- /dev/null +++ b/Tests/RunCMake/return/PropagateNothing.cmake @@ -0,0 +1,2 @@ + +return(PROPAGATE) diff --git a/Tests/RunCMake/return/RunCMakeTest.cmake b/Tests/RunCMake/return/RunCMakeTest.cmake index 2cc6c9d..f9e06a5 100644 --- a/Tests/RunCMake/return/RunCMakeTest.cmake +++ b/Tests/RunCMake/return/RunCMakeTest.cmake @@ -1,3 +1,12 @@ include(RunCMake) run_cmake(ReturnFromForeach) + +run_cmake(WrongArgument) +run_cmake(PropagateNothing) +run_cmake(PropagateFromFunction) +run_cmake(PropagateFromDirectory) + +run_cmake(CMP0140-NEW) +run_cmake(CMP0140-OLD) +run_cmake(CMP0140-WARN) diff --git a/Tests/RunCMake/return/WrongArgument-result.txt b/Tests/RunCMake/return/WrongArgument-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/return/WrongArgument-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/return/WrongArgument-stderr.txt b/Tests/RunCMake/return/WrongArgument-stderr.txt new file mode 100644 index 0000000..4d1c5ad --- /dev/null +++ b/Tests/RunCMake/return/WrongArgument-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at WrongArgument.cmake:[0-9]+ \(return\): + return called with unsupported argument "WRONG_ARG" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/return/WrongArgument.cmake b/Tests/RunCMake/return/WrongArgument.cmake new file mode 100644 index 0000000..d03b19f --- /dev/null +++ b/Tests/RunCMake/return/WrongArgument.cmake @@ -0,0 +1,2 @@ + +return(WRONG_ARG) diff --git a/Tests/RunCMake/return/subdir/CMakeLists.txt b/Tests/RunCMake/return/subdir/CMakeLists.txt new file mode 100644 index 0000000..e575d47 --- /dev/null +++ b/Tests/RunCMake/return/subdir/CMakeLists.txt @@ -0,0 +1,5 @@ + +set(VAR1 "set") +unset(VAR2) + +return(PROPAGATE VAR1 VAR2) diff --git a/Tests/RunCMake/string/JSON.cmake b/Tests/RunCMake/string/JSON.cmake index ab4194d..255c16a 100644 --- a/Tests/RunCMake/string/JSON.cmake +++ b/Tests/RunCMake/string/JSON.cmake @@ -129,7 +129,7 @@ assert_strequal("${error}" "member '0' not found") string(JSON result ERROR_VARIABLE error GET "${json1}" array 10) assert_strequal("${result}" "array-10-NOTFOUND") -assert_strequal("${error}" "expected an index less then 4 got '10'") +assert_strequal("${error}" "expected an index less than 4 got '10'") string(JSON result ERROR_VARIABLE error GET "${json1}" array 2 some notThere) assert_strequal("${result}" "array-2-some-notThere-NOTFOUND") @@ -240,7 +240,7 @@ endif() string(JSON result ERROR_VARIABLE error MEMBER "${json1}" values 100) assert_strequal("${result}" "values-100-NOTFOUND") -assert_strequal("${error}" "expected an index less then 5 got '100'") +assert_strequal("${error}" "expected an index less than 5 got '100'") # Test length loops string(JSON arrayLength ERROR_VARIABLE error LENGTH "${json1}" types array) @@ -301,7 +301,7 @@ assert_json_equal("${error}" "${result}" string(JSON result ERROR_VARIABLE error REMOVE ${json2} array 100) assert_strequal("${result}" "array-100-NOTFOUND") -assert_strequal("${error}" "expected an index less then 4 got '100'") +assert_strequal("${error}" "expected an index less than 4 got '100'") # Test SET string(JSON result ERROR_VARIABLE error SET ${json2} new 5) diff --git a/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt new file mode 100644 index 0000000..f04e43f --- /dev/null +++ b/Tests/RunCMake/target_compile_options/CMP0101-BEFORE_keyword-stderr.txt @@ -0,0 +1,10 @@ +^CMake Deprecation Warning at CMP0101-BEFORE_keyword.cmake:[0-9]+ \(cmake_policy\): + The OLD behavior for policy CMP0101 will be removed from a future version + of CMake. + + The cmake-policies\(7\) manual explains that the OLD behaviors of all + policies are deprecated and that a policy should be set to OLD only under + specific short-term circumstances. Projects should be ported to the NEW + behavior and not rely on setting a policy to OLD. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake index 021de41..9b6581c 100644 --- a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/RunCMakeTest.cmake @@ -90,12 +90,22 @@ if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES run_cmake_target(apple_framework target-framework main-target-framework) run_cmake_target(apple_framework target-reexport_framework main-target-reexport_framework) run_cmake_target(apple_framework target-weak_framework main-target-weak_framework) + + if(RunCMake_GENERATOR_IS_MULTI_CONFIG AND (NOT XCODE OR XCODE_VERSION GREATER_EQUAL 13)) + run_cmake_target(apple_framework target-framework-postfix main-target-framework-postfix) + run_cmake_target(apple_framework target-reexport_framework-postfix main-target-reexport_framework-postfix) + run_cmake_target(apple_framework target-weak_framework-postfix main-target-weak_framework-postfix) + endif() endif() if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION GREATER_EQUAL "12") run_cmake_target(apple_framework needed_framework main-needed_framework) run_cmake_target(apple_framework target-needed_framework main-target-needed_framework) + + if(RunCMake_GENERATOR_IS_MULTI_CONFIG AND (NOT XCODE OR XCODE_VERSION GREATER_EQUAL 13)) + run_cmake_target(apple_framework target-needed_framework-postfix main-target-needed_framework-postfix) + endif() endif() # Apple library features diff --git a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/apple_framework.cmake b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/apple_framework.cmake index e9a93e9..ca0e72d 100644 --- a/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/apple_framework.cmake +++ b/Tests/RunCMake/target_link_libraries-LINK_LIBRARY/apple_framework.cmake @@ -59,3 +59,33 @@ target_link_libraries(main-target-reexport_framework PRIVATE "$<LINK_LIBRARY:FRA # feature WEAK_FRAMEWORK add_executable(main-target-weak_framework main.mm) target_link_libraries(main-target-weak_framework PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,target-framework>") + + + +get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTI_CONFIG) + add_library(target-framework-postfix SHARED foo.mm) + set_target_properties(target-framework-postfix PROPERTIES FRAMEWORK TRUE + FRAMEWORK_MULTI_CONFIG_POSTFIX_RELEASE "_release") + target_link_libraries(target-framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>") + + + # feature FRAMEWORK + add_executable(main-target-framework-postfix main.mm) + target_link_libraries(main-target-framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:FRAMEWORK,target-framework-postfix>") + + + # feature NEEDED_FRAMEWORK + add_executable(main-target-needed_framework-postfix main.mm) + target_link_libraries(main-target-needed_framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:NEEDED_FRAMEWORK,target-framework-postfix>") + + + # feature REEXPORT_FRAMEWORK + add_executable(main-target-reexport_framework-postfix main.mm) + target_link_libraries(main-target-reexport_framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,target-framework-postfix>") + + + # feature WEAK_FRAMEWORK + add_executable(main-target-weak_framework-postfix main.mm) + target_link_libraries(main-target-weak_framework-postfix PRIVATE "$<LINK_LIBRARY:FRAMEWORK,Foundation>" "$<LINK_LIBRARY:REEXPORT_FRAMEWORK,target-framework-postfix>") +endif() diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt new file mode 100644 index 0000000..042d67d --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental-stderr.txt @@ -0,0 +1,12 @@ +^CMake Warning \(dev\) at FileSetDefaultWrongTypeExperimental.cmake:6 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error at FileSetDefaultWrongTypeExperimental\.cmake:[0-9]+ \(target_sources\): + target_sources File set TYPE may only be "HEADERS", "CXX_MODULES", or + "CXX_MODULE_HEADER_UNITS" +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake new file mode 100644 index 0000000..5ade637 --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetDefaultWrongTypeExperimental.cmake @@ -0,0 +1,6 @@ +enable_language(C) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046") + +add_library(lib1 STATIC empty.c) +target_sources(lib1 PRIVATE FILE_SET UNKNOWN) diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt new file mode 100644 index 0000000..a1b784f --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental-stderr.txt @@ -0,0 +1,12 @@ +^CMake Warning \(dev\) at FileSetWrongTypeExperimental.cmake:6 \(target_sources\): + CMake's C\+\+ module support is experimental. It is meant only for + experimentation and feedback to CMake developers. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) +This warning is for project developers. Use -Wno-dev to suppress it. + +CMake Error at FileSetWrongTypeExperimental\.cmake:[0-9]+ \(target_sources\): + target_sources File set TYPE may only be "HEADERS", "CXX_MODULES", or + "CXX_MODULE_HEADER_UNITS" +Call Stack \(most recent call first\): + CMakeLists\.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake new file mode 100644 index 0000000..332441c --- /dev/null +++ b/Tests/RunCMake/target_sources/FileSetWrongTypeExperimental.cmake @@ -0,0 +1,6 @@ +enable_language(C) + +set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046") + +add_library(lib1 STATIC empty.c) +target_sources(lib1 PRIVATE FILE_SET a TYPE UNKNOWN) diff --git a/Tests/RunCMake/target_sources/RunCMakeTest.cmake b/Tests/RunCMake/target_sources/RunCMakeTest.cmake index 6a3c7b9..7c67c3f 100644 --- a/Tests/RunCMake/target_sources/RunCMakeTest.cmake +++ b/Tests/RunCMake/target_sources/RunCMakeTest.cmake @@ -26,6 +26,8 @@ run_cmake(FileSetProperties) run_cmake(FileSetNoType) run_cmake(FileSetWrongType) run_cmake(FileSetDefaultWrongType) +run_cmake(FileSetWrongTypeExperimental) +run_cmake(FileSetDefaultWrongTypeExperimental) run_cmake(FileSetChangeScope) run_cmake(FileSetChangeType) run_cmake(FileSetWrongBaseDirs) diff --git a/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt b/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt index 652bcfc..4e41a19 100644 --- a/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt +++ b/Tests/RunCMake/try_compile/BadLinkLibraries-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at BadLinkLibraries.cmake:2 \(try_compile\): +CMake Error at BadLinkLibraries.cmake:[0-9]+ \(try_compile\): Only libraries may be used as try_compile or try_run IMPORTED LINK_LIBRARIES. Got not_a_library of type UTILITY. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/try_compile/BadLinkLibraries.cmake b/Tests/RunCMake/try_compile/BadLinkLibraries.cmake index e8b5add..b758e23 100644 --- a/Tests/RunCMake/try_compile/BadLinkLibraries.cmake +++ b/Tests/RunCMake/try_compile/BadLinkLibraries.cmake @@ -1,3 +1,7 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + add_custom_target(not_a_library) -try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c LINK_LIBRARIES not_a_library) diff --git a/Tests/RunCMake/try_compile/BadSources1-stderr.txt b/Tests/RunCMake/try_compile/BadSources1-stderr.txt index 864a294..ddcba4f 100644 --- a/Tests/RunCMake/try_compile/BadSources1-stderr.txt +++ b/Tests/RunCMake/try_compile/BadSources1-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at BadSources1.cmake:1 \(try_compile\): +CMake Error at BadSources1.cmake:[0-9]+ \(try_compile\): Unknown extension ".c" for file .*/Tests/RunCMake/try_compile/src.c diff --git a/Tests/RunCMake/try_compile/BadSources1.cmake b/Tests/RunCMake/try_compile/BadSources1.cmake index aa4dc5e..c95935d 100644 --- a/Tests/RunCMake/try_compile/BadSources1.cmake +++ b/Tests/RunCMake/try_compile/BadSources1.cmake @@ -1 +1,3 @@ -try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c) +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c) diff --git a/Tests/RunCMake/try_compile/BadSources2-stderr.txt b/Tests/RunCMake/try_compile/BadSources2-stderr.txt index 3313f99..953dd9c 100644 --- a/Tests/RunCMake/try_compile/BadSources2-stderr.txt +++ b/Tests/RunCMake/try_compile/BadSources2-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at BadSources2.cmake:2 \(try_compile\): +CMake Error at BadSources2.cmake:[0-9]+ \(try_compile\): Unknown extension ".cxx" for file .*/Tests/RunCMake/try_compile/src.cxx diff --git a/Tests/RunCMake/try_compile/BadSources2.cmake b/Tests/RunCMake/try_compile/BadSources2.cmake index ed2b036..3f22bb6 100644 --- a/Tests/RunCMake/try_compile/BadSources2.cmake +++ b/Tests/RunCMake/try_compile/BadSources2.cmake @@ -1,5 +1,6 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) enable_language(C) -try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c - ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx ) diff --git a/Tests/RunCMake/try_compile/BinDirEmpty-result.txt b/Tests/RunCMake/try_compile/BinDirEmpty-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/BinDirEmpty-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/BinDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/BinDirEmpty-stderr.txt new file mode 100644 index 0000000..b1f5ae3 --- /dev/null +++ b/Tests/RunCMake/try_compile/BinDirEmpty-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at BinDirEmpty.cmake:[0-9]+ \(try_compile\): + No <bindir> specified. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_compile/BinDirEmpty.cmake b/Tests/RunCMake/try_compile/BinDirEmpty.cmake new file mode 100644 index 0000000..7bea43d --- /dev/null +++ b/Tests/RunCMake/try_compile/BinDirEmpty.cmake @@ -0,0 +1 @@ +try_compile(resultVar "" ${CMAKE_CURRENT_SOURCE_DIR}/src.c) diff --git a/Tests/RunCMake/try_compile/BinDirRelative-result.txt b/Tests/RunCMake/try_compile/BinDirRelative-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/BinDirRelative-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/BinDirRelative-stderr.txt b/Tests/RunCMake/try_compile/BinDirRelative-stderr.txt new file mode 100644 index 0000000..a7b6302 --- /dev/null +++ b/Tests/RunCMake/try_compile/BinDirRelative-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at BinDirRelative.cmake:[0-9]+ \(try_compile\): + <bindir> is not an absolute path: + + 'bin_dir_relative' +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_compile/BinDirRelative.cmake b/Tests/RunCMake/try_compile/BinDirRelative.cmake new file mode 100644 index 0000000..8deda11 --- /dev/null +++ b/Tests/RunCMake/try_compile/BinDirRelative.cmake @@ -0,0 +1 @@ +try_compile(resultVar bin_dir_relative ${CMAKE_CURRENT_SOURCE_DIR}/src.c) diff --git a/Tests/RunCMake/try_compile/BuildType.cmake b/Tests/RunCMake/try_compile/BuildType.cmake new file mode 100644 index 0000000..8d7e3be --- /dev/null +++ b/Tests/RunCMake/try_compile/BuildType.cmake @@ -0,0 +1,8 @@ +enable_language(C) +set(CMAKE_BUILD_TYPE RelWithDebInfo) + +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT + ${try_compile_bindir_or_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin" + ) diff --git a/Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake b/Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake new file mode 100644 index 0000000..a822156 --- /dev/null +++ b/Tests/RunCMake/try_compile/BuildTypeAsFlag.cmake @@ -0,0 +1,9 @@ +enable_language(C) +set(CMAKE_BUILD_TYPE RelWithDebInfo) + +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT + ${try_compile_bindir_or_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin" + CMAKE_FLAGS "-DCMAKE_BUILD_TYPE=Release" + ) diff --git a/Tests/RunCMake/try_compile/CStandard-stderr.txt b/Tests/RunCMake/try_compile/CStandard-stderr.txt index 209afcc..c3c48a1 100644 --- a/Tests/RunCMake/try_compile/CStandard-stderr.txt +++ b/Tests/RunCMake/try_compile/CStandard-stderr.txt @@ -1,4 +1,4 @@ -^CMake Error at .*/Tests/RunCMake/try_compile/CStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\): +^CMake Error at .*/Tests/RunCMake/try_compile/CStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\): C_STANDARD is set to invalid value '3' + CMake Error at CStandard.cmake:[0-9]+ \(try_compile\): diff --git a/Tests/RunCMake/try_compile/CStandard.cmake b/Tests/RunCMake/try_compile/CStandard.cmake index 2849ed4..6ac04db 100644 --- a/Tests/RunCMake/try_compile/CStandard.cmake +++ b/Tests/RunCMake/try_compile/CStandard.cmake @@ -1,7 +1,11 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(C) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c C_STANDARD 3 OUTPUT_VARIABLE out ) + message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/CStandardGNU.cmake b/Tests/RunCMake/try_compile/CStandardGNU.cmake index 79ae874..10a4384 100644 --- a/Tests/RunCMake/try_compile/CStandardGNU.cmake +++ b/Tests/RunCMake/try_compile/CStandardGNU.cmake @@ -1,23 +1,30 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(C) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c C_STANDARD 99 C_STANDARD_REQUIRED 1 C_EXTENSIONS 0 OUTPUT_VARIABLE out ) + if(NOT result) message(FATAL_ERROR "try_compile failed:\n${out}") endif() cmake_policy(SET CMP0067 NEW) + set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED 1) set(CMAKE_C_EXTENSIONS 0) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/CStandardGNU.c OUTPUT_VARIABLE out ) + if(NOT result) message(FATAL_ERROR "try_compile failed:\n${out}") endif() diff --git a/Tests/RunCMake/try_compile/CStandardNoDefault.cmake b/Tests/RunCMake/try_compile/CStandardNoDefault.cmake index 97e72ea..f4dd5ae 100644 --- a/Tests/RunCMake/try_compile/CStandardNoDefault.cmake +++ b/Tests/RunCMake/try_compile/CStandardNoDefault.cmake @@ -1,9 +1,13 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(C) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c C_STANDARD 3 # bogus, but not used OUTPUT_VARIABLE out ) + if(NOT result) message(FATAL_ERROR "try_compile failed:\n${out}") endif() diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt index 5d09c0c..8c49302 100644 --- a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt +++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at CopyFileErrorNoCopyFile.cmake:1 \(try_compile\): +CMake Error at CopyFileErrorNoCopyFile.cmake:[0-9]+ \(try_compile\): COPY_FILE_ERROR may be used only with COPY_FILE Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake index 8d7cb0e..8d15b3d 100644 --- a/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake +++ b/Tests/RunCMake/try_compile/CopyFileErrorNoCopyFile.cmake @@ -1,2 +1,4 @@ -try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c COPY_FILE_ERROR _copied) diff --git a/Tests/RunCMake/try_compile/CudaStandard-stderr.txt b/Tests/RunCMake/try_compile/CudaStandard-stderr.txt index bcf95d5..52dff8f 100644 --- a/Tests/RunCMake/try_compile/CudaStandard-stderr.txt +++ b/Tests/RunCMake/try_compile/CudaStandard-stderr.txt @@ -1,4 +1,4 @@ -^CMake Error at .*/Tests/RunCMake/try_compile/CudaStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\): +^CMake Error at .*/Tests/RunCMake/try_compile/CudaStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\): CUDA_STANDARD is set to invalid value '4' + CMake Error at CudaStandard.cmake:[0-9]+ \(try_compile\): diff --git a/Tests/RunCMake/try_compile/CudaStandard.cmake b/Tests/RunCMake/try_compile/CudaStandard.cmake index a230424..0be89be 100644 --- a/Tests/RunCMake/try_compile/CudaStandard.cmake +++ b/Tests/RunCMake/try_compile/CudaStandard.cmake @@ -1,7 +1,11 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(CUDA) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cu + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.cu CUDA_STANDARD 4 OUTPUT_VARIABLE out ) + message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/CxxStandard-stderr.txt b/Tests/RunCMake/try_compile/CxxStandard-stderr.txt index ec7245f..55a06e2 100644 --- a/Tests/RunCMake/try_compile/CxxStandard-stderr.txt +++ b/Tests/RunCMake/try_compile/CxxStandard-stderr.txt @@ -1,6 +1,17 @@ -^CMake Error at .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\): +^(CMake Error in .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt: + The CXX_STANDARD property on target "cmTC_[0-9a-f]*" contained an invalid + value: "3". + + +)?CMake Error at .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\): CXX_STANDARD is set to invalid value '3' -+ + +( +CMake Error in .*/Tests/RunCMake/try_compile/CxxStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt: + The CXX_STANDARD property on target "cmTC_[0-9a-f]*" contained an invalid + value: "3". + +)? CMake Error at CxxStandard.cmake:[0-9]+ \(try_compile\): Failed to generate test project build system. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/try_compile/CxxStandard.cmake b/Tests/RunCMake/try_compile/CxxStandard.cmake index bcb49b9..e5b4e78 100644 --- a/Tests/RunCMake/try_compile/CxxStandard.cmake +++ b/Tests/RunCMake/try_compile/CxxStandard.cmake @@ -1,7 +1,11 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(CXX) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx CXX_STANDARD 3 OUTPUT_VARIABLE out ) + message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/CxxStandardGNU.cmake b/Tests/RunCMake/try_compile/CxxStandardGNU.cmake index e714fe4..552d99d 100644 --- a/Tests/RunCMake/try_compile/CxxStandardGNU.cmake +++ b/Tests/RunCMake/try_compile/CxxStandardGNU.cmake @@ -1,23 +1,30 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(CXX) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx CXX_STANDARD 11 CXX_STANDARD_REQUIRED 1 CXX_EXTENSIONS 0 OUTPUT_VARIABLE out ) + if(NOT result) message(FATAL_ERROR "try_compile failed:\n${out}") endif() cmake_policy(SET CMP0067 NEW) + set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED 1) set(CMAKE_CXX_EXTENSIONS 0) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/CxxStandardGNU.cxx OUTPUT_VARIABLE out ) + if(NOT result) message(FATAL_ERROR "try_compile failed:\n${out}") endif() diff --git a/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake b/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake index 35caa9d..e0ebfee 100644 --- a/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake +++ b/Tests/RunCMake/try_compile/CxxStandardNoDefault.cmake @@ -1,9 +1,13 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(CXX) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.cxx CXX_STANDARD 3 # bogus, but not used OUTPUT_VARIABLE out ) + if(NOT result) message(FATAL_ERROR "try_compile failed:\n${out}") endif() diff --git a/Tests/RunCMake/try_compile/EmptyListArgs.cmake b/Tests/RunCMake/try_compile/EmptyListArgs.cmake new file mode 100644 index 0000000..5cd7465 --- /dev/null +++ b/Tests/RunCMake/try_compile/EmptyListArgs.cmake @@ -0,0 +1,11 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + +enable_language(C) + +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + CMAKE_FLAGS # no values + COMPILE_DEFINITIONS # no values + LINK_LIBRARIES # no values + LINK_OPTIONS # no values + ) diff --git a/Tests/RunCMake/try_compile/EmptyValueArgs-result.txt b/Tests/RunCMake/try_compile/EmptyValueArgs-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/EmptyValueArgs-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/EmptyValueArgs-stderr.txt b/Tests/RunCMake/try_compile/EmptyValueArgs-stderr.txt new file mode 100644 index 0000000..b1344bd --- /dev/null +++ b/Tests/RunCMake/try_compile/EmptyValueArgs-stderr.txt @@ -0,0 +1,9 @@ +CMake Error at EmptyValueArgs.cmake:[0-9]+ \(try_compile\): + COPY_FILE must be followed by a file path +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) ++ +CMake Error at EmptyValueArgs.cmake:[0-9]+ \(try_compile\): + COPY_FILE_ERROR must be followed by a variable name +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/try_compile/EmptyValueArgs.cmake b/Tests/RunCMake/try_compile/EmptyValueArgs.cmake new file mode 100644 index 0000000..fda4f10 --- /dev/null +++ b/Tests/RunCMake/try_compile/EmptyValueArgs.cmake @@ -0,0 +1,7 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE "") +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE "x" COPY_FILE_ERROR "") diff --git a/Tests/RunCMake/try_compile/EnvConfig.cmake b/Tests/RunCMake/try_compile/EnvConfig.cmake index 4040c59..6e66825 100644 --- a/Tests/RunCMake/try_compile/EnvConfig.cmake +++ b/Tests/RunCMake/try_compile/EnvConfig.cmake @@ -1,3 +1,5 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(C) set(ENV{CMAKE_BUILD_TYPE} "Bad") @@ -6,8 +8,8 @@ set(ENV{CMAKE_CONFIGURATION_TYPES} "Bad;Debug") add_library(tc_defs INTERFACE IMPORTED) target_compile_definitions(tc_defs INTERFACE "TC_CONFIG_$<UPPER_CASE:$<CONFIG>>") -try_compile(ENV_CONFIG_RESULT "${CMAKE_BINARY_DIR}" - SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/EnvConfig.c" +try_compile(ENV_CONFIG_RESULT "${try_compile_bindir_or_SOURCES}" + ${try_compile_redundant_SOURCES} "${CMAKE_CURRENT_SOURCE_DIR}/EnvConfig.c" COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/EnvConfig.bin" OUTPUT_VARIABLE tc_output LINK_LIBRARIES tc_defs diff --git a/Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake b/Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake index 6d29069..1ead4c2 100644 --- a/Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake +++ b/Tests/RunCMake/try_compile/ISPCDuplicateTarget.cmake @@ -1,8 +1,12 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(ISPC) -set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16 - avx512skx-i32x16) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc + +set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16 avx512skx-i32x16) + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc OUTPUT_VARIABLE out ) + message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake b/Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake index 7f59c14..e08e25f 100644 --- a/Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake +++ b/Tests/RunCMake/try_compile/ISPCDuplicateTargetNinja.cmake @@ -1,11 +1,16 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(ISPC) -set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16 - avx512skx-i32x16) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc + +set(CMAKE_ISPC_INSTRUCTION_SETS avx512skx-i32x16 avx512skx-i32x16) + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc OUTPUT_VARIABLE out ) + message("try_compile output:\n${out}") + if(NOT result) message(FATAL_ERROR "making Ninja and Ninja Multi-Config behave the same") endif() diff --git a/Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake b/Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake index c1ab6f2..2276bd3 100644 --- a/Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake +++ b/Tests/RunCMake/try_compile/ISPCInvalidTarget.cmake @@ -1,7 +1,12 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(ISPC) + set(CMAKE_ISPC_INSTRUCTION_SETS "avxknl-i32x16") -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc OUTPUT_VARIABLE out ) + message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/ISPCTargets.cmake b/Tests/RunCMake/try_compile/ISPCTargets.cmake index 0d3bd43..bd45569 100644 --- a/Tests/RunCMake/try_compile/ISPCTargets.cmake +++ b/Tests/RunCMake/try_compile/ISPCTargets.cmake @@ -1,7 +1,12 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(ISPC) + set(CMAKE_ISPC_INSTRUCTION_SETS avx512knl-i32x16 avx512skx-i32x16) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.ispc OUTPUT_VARIABLE out ) + message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/NoArgs-stderr.txt b/Tests/RunCMake/try_compile/NoArgs-stderr.txt index 8808fd1..4228580 100644 --- a/Tests/RunCMake/try_compile/NoArgs-stderr.txt +++ b/Tests/RunCMake/try_compile/NoArgs-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at NoArgs.cmake:1 \(try_compile\): - try_compile unknown error. +CMake Error at NoArgs.cmake:[0-9]+ \(try_compile\): + The try_compile\(\) command requires at least 3 arguments. Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoCStandard-result.txt b/Tests/RunCMake/try_compile/NoCStandard-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCStandard-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/NoCStandard-stderr.txt b/Tests/RunCMake/try_compile/NoCStandard-stderr.txt new file mode 100644 index 0000000..e0bb9ed --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCStandard-stderr.txt @@ -0,0 +1,7 @@ +CMake Error at NoCStandard.cmake:[0-9]+ \(try_compile\): + Error after keyword "C_STANDARD": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoCStandard.cmake b/Tests/RunCMake/try_compile/NoCStandard.cmake new file mode 100644 index 0000000..e0d0478 --- /dev/null +++ b/Tests/RunCMake/try_compile/NoCStandard.cmake @@ -0,0 +1,4 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(result ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + C_STANDARD) diff --git a/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt index d65d9488..55ba687 100644 --- a/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt +++ b/Tests/RunCMake/try_compile/NoCopyFile-stderr.txt @@ -1,4 +1,7 @@ -CMake Error at NoCopyFile.cmake:1 \(try_compile\): - COPY_FILE must be followed by a file path +CMake Error at NoCopyFile.cmake:[0-9]+ \(try_compile\): + Error after keyword "COPY_FILE": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoCopyFile.cmake b/Tests/RunCMake/try_compile/NoCopyFile.cmake index 8c648ff..270dff9 100644 --- a/Tests/RunCMake/try_compile/NoCopyFile.cmake +++ b/Tests/RunCMake/try_compile/NoCopyFile.cmake @@ -1,2 +1,4 @@ -try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c COPY_FILE) diff --git a/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt index e889524..008d4e9 100644 --- a/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt +++ b/Tests/RunCMake/try_compile/NoCopyFile2-stderr.txt @@ -1,4 +1,7 @@ -CMake Error at NoCopyFile2.cmake:1 \(try_compile\): - COPY_FILE must be followed by a file path +CMake Error at NoCopyFile2.cmake:[0-9]+ \(try_compile\): + Error after keyword "COPY_FILE": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoCopyFile2.cmake b/Tests/RunCMake/try_compile/NoCopyFile2.cmake index 04b7f68..2ea8182 100644 --- a/Tests/RunCMake/try_compile/NoCopyFile2.cmake +++ b/Tests/RunCMake/try_compile/NoCopyFile2.cmake @@ -1,2 +1,4 @@ -try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c COPY_FILE CMAKE_FLAGS -DA=B) diff --git a/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt index ed552fd..7ca185d 100644 --- a/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt +++ b/Tests/RunCMake/try_compile/NoCopyFileError-stderr.txt @@ -1,4 +1,7 @@ -CMake Error at NoCopyFileError.cmake:1 \(try_compile\): - COPY_FILE_ERROR must be followed by a variable name +CMake Error at NoCopyFileError.cmake:[0-9]+ \(try_compile\): + Error after keyword "COPY_FILE_ERROR": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoCopyFileError.cmake b/Tests/RunCMake/try_compile/NoCopyFileError.cmake index d4d69ee..1a56e86 100644 --- a/Tests/RunCMake/try_compile/NoCopyFileError.cmake +++ b/Tests/RunCMake/try_compile/NoCopyFileError.cmake @@ -1,2 +1,4 @@ -try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copied.bin COPY_FILE_ERROR) diff --git a/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt b/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt index 18ad751..ec29f0b 100644 --- a/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt +++ b/Tests/RunCMake/try_compile/NoOutputVariable-stderr.txt @@ -1,4 +1,7 @@ -CMake Error at NoOutputVariable.cmake:1 \(try_compile\): - OUTPUT_VARIABLE must be followed by a variable name +CMake Error at NoOutputVariable.cmake:[0-9]+ \(try_compile\): + Error after keyword "OUTPUT_VARIABLE": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoOutputVariable.cmake b/Tests/RunCMake/try_compile/NoOutputVariable.cmake index 3b9cb34..13dc4b4 100644 --- a/Tests/RunCMake/try_compile/NoOutputVariable.cmake +++ b/Tests/RunCMake/try_compile/NoOutputVariable.cmake @@ -1,2 +1,4 @@ -try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c OUTPUT_VARIABLE) diff --git a/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt b/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt index 8b2cc25..dd34559 100644 --- a/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt +++ b/Tests/RunCMake/try_compile/NoOutputVariable2-stderr.txt @@ -1,4 +1,7 @@ -CMake Error at NoOutputVariable2.cmake:1 \(try_compile\): - OUTPUT_VARIABLE must be followed by a variable name +CMake Error at NoOutputVariable2.cmake:[0-9]+ \(try_compile\): + Error after keyword "OUTPUT_VARIABLE": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NoOutputVariable2.cmake b/Tests/RunCMake/try_compile/NoOutputVariable2.cmake index ad9ac9a..4d5dda3 100644 --- a/Tests/RunCMake/try_compile/NoOutputVariable2.cmake +++ b/Tests/RunCMake/try_compile/NoOutputVariable2.cmake @@ -1,2 +1,4 @@ -try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c OUTPUT_VARIABLE CMAKE_FLAGS -DA=B) diff --git a/Tests/RunCMake/try_compile/NoSources-stderr.txt b/Tests/RunCMake/try_compile/NoSources-stderr.txt index 023032b..55603dc 100644 --- a/Tests/RunCMake/try_compile/NoSources-stderr.txt +++ b/Tests/RunCMake/try_compile/NoSources-stderr.txt @@ -1,4 +1,7 @@ -CMake Error at NoSources.cmake:1 \(try_compile\): - SOURCES must be followed by at least one source file +CMake Error at NoSources.cmake:[0-9]+ \(try_compile\): + Error after keyword "SOURCES": + + missing required value + Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt index 025e658..dcd5c7a 100644 --- a/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt +++ b/Tests/RunCMake/try_compile/NonSourceCompileDefinitions-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at NonSourceCompileDefinitions.cmake:1 \(try_compile\): - COMPILE_DEFINITIONS specified on a srcdir type TRY_COMPILE +CMake Error at NonSourceCompileDefinitions.cmake:[0-9]+ \(try_compile\): + COMPILE_DEFINITIONS allowed only in source file signature Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt b/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt index f5893e1..1b7dfeb 100644 --- a/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt +++ b/Tests/RunCMake/try_compile/NonSourceCopyFile-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at NonSourceCopyFile.cmake:1 \(try_compile\): - COPY_FILE specified on a srcdir type TRY_COMPILE +CMake Error at NonSourceCopyFile.cmake:[0-9]+ \(try_compile\): + COPY_FILE allowed only in source file signature Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt b/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt index f1b4df9..59f1d73 100644 --- a/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt +++ b/Tests/RunCMake/try_compile/ObjCStandard-stderr.txt @@ -1,4 +1,4 @@ -^CMake Error at .*/Tests/RunCMake/try_compile/ObjCStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\): +^CMake Error at .*/Tests/RunCMake/try_compile/ObjCStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\): OBJC_STANDARD is set to invalid value '3' + CMake Error at ObjCStandard.cmake:[0-9]+ \(try_compile\): diff --git a/Tests/RunCMake/try_compile/ObjCStandard.cmake b/Tests/RunCMake/try_compile/ObjCStandard.cmake index b2066f9..a691ddd 100644 --- a/Tests/RunCMake/try_compile/ObjCStandard.cmake +++ b/Tests/RunCMake/try_compile/ObjCStandard.cmake @@ -1,7 +1,11 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(OBJC) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.m + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.m OBJC_STANDARD 3 OUTPUT_VARIABLE out ) + message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt b/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt index a2f91b4..21fa20f 100644 --- a/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt +++ b/Tests/RunCMake/try_compile/ObjCxxStandard-stderr.txt @@ -1,4 +1,4 @@ -^CMake Error at .*/Tests/RunCMake/try_compile/ObjCxxStandard-build/CMakeFiles/CMakeTmp/CMakeLists.txt:[0-9]+ \(add_executable\): +^CMake Error at .*/Tests/RunCMake/try_compile/ObjCxxStandard-build/CMakeFiles/CMake(Tmp|Scratch/TryCompile-[^/]+)/CMakeLists.txt:[0-9]+ \(add_executable\): OBJCXX_STANDARD is set to invalid value '3' + CMake Error at ObjCxxStandard.cmake:[0-9]+ \(try_compile\): diff --git a/Tests/RunCMake/try_compile/ObjCxxStandard.cmake b/Tests/RunCMake/try_compile/ObjCxxStandard.cmake index 1221805..b03f560 100644 --- a/Tests/RunCMake/try_compile/ObjCxxStandard.cmake +++ b/Tests/RunCMake/try_compile/ObjCxxStandard.cmake @@ -1,7 +1,11 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(OBJCXX) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.mm + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.mm OBJCXX_STANDARD 3 OUTPUT_VARIABLE out ) + message("try_compile output:\n${out}") diff --git a/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-result.txt b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-stderr.txt new file mode 100644 index 0000000..e9ec450 --- /dev/null +++ b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at OldProjectBinDirEmpty.cmake:[0-9]+ \(try_compile\): + No <bindir> specified. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_compile/OldProjectBinDirEmpty.cmake b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty.cmake new file mode 100644 index 0000000..fa922d9 --- /dev/null +++ b/Tests/RunCMake/try_compile/OldProjectBinDirEmpty.cmake @@ -0,0 +1 @@ +try_compile(RESULT "" ${CMAKE_CURRENT_SOURCE_DIR}/proj Foo) diff --git a/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-result.txt b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-stderr.txt new file mode 100644 index 0000000..47dd60f --- /dev/null +++ b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at OldProjectSrcDirEmpty.cmake:[0-9]+ \(try_compile\): + No <srcdir> specified. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty.cmake b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty.cmake new file mode 100644 index 0000000..dfbfba6 --- /dev/null +++ b/Tests/RunCMake/try_compile/OldProjectSrcDirEmpty.cmake @@ -0,0 +1 @@ +try_compile(RESULT ${CMAKE_CURRENT_BINARY_DIR} "" Foo) diff --git a/Tests/RunCMake/try_compile/OneArg-stderr.txt b/Tests/RunCMake/try_compile/OneArg-stderr.txt index 12835be..a2e983e 100644 --- a/Tests/RunCMake/try_compile/OneArg-stderr.txt +++ b/Tests/RunCMake/try_compile/OneArg-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at OneArg.cmake:1 \(try_compile\): - try_compile unknown error. +CMake Error at OneArg.cmake:[0-9]+ \(try_compile\): + The try_compile\(\) command requires at least 3 arguments. Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/OutputDirAsFlag.cmake b/Tests/RunCMake/try_compile/OutputDirAsFlag.cmake new file mode 100644 index 0000000..1214bbb --- /dev/null +++ b/Tests/RunCMake/try_compile/OutputDirAsFlag.cmake @@ -0,0 +1,9 @@ +enable_language(C) +set(CMAKE_BUILD_TYPE RelWithDebInfo) + +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) +try_compile(RESULT + ${try_compile_bindir_or_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin" + CMAKE_FLAGS "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=bin" + ) diff --git a/Tests/RunCMake/try_compile/PlatformVariables-stderr.txt b/Tests/RunCMake/try_compile/PlatformVariables-stderr.txt new file mode 100644 index 0000000..4a42b2d --- /dev/null +++ b/Tests/RunCMake/try_compile/PlatformVariables-stderr.txt @@ -0,0 +1,11 @@ +^CMake Debug Log at [^ +]*/Modules/CMakeDetermineCompilerABI.cmake:[0-9]+ \(try_compile\): + Executing try_compile \(CMAKE_C_ABI_COMPILED\) in: + + [^ +]*/Tests/RunCMake/try_compile/PlatformVariables-build/CMakeFiles/CMakeScratch/TryCompile-[^/]+ +Call Stack \(most recent call first\): + [^ +]*/Modules/CMakeTestCCompiler.cmake:[0-9]+ \(CMAKE_DETERMINE_COMPILER_ABI\) + PlatformVariables.cmake:[0-9]+ \(enable_language\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/try_compile/ProjectBinDirEmpty-result.txt b/Tests/RunCMake/try_compile/ProjectBinDirEmpty-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectBinDirEmpty-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/ProjectBinDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/ProjectBinDirEmpty-stderr.txt new file mode 100644 index 0000000..57a2bd0 --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectBinDirEmpty-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at ProjectBinDirEmpty.cmake:[0-9]+ \(try_compile\): + No <bindir> specified. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_compile/ProjectBinDirEmpty.cmake b/Tests/RunCMake/try_compile/ProjectBinDirEmpty.cmake new file mode 100644 index 0000000..e867cc6 --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectBinDirEmpty.cmake @@ -0,0 +1,4 @@ +try_compile(RESULT PROJECT Foo + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/proj + BINARY_DIR "" + ) diff --git a/Tests/RunCMake/try_compile/ProjectCopyFile-result.txt b/Tests/RunCMake/try_compile/ProjectCopyFile-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectCopyFile-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/try_compile/ProjectCopyFile-stderr.txt b/Tests/RunCMake/try_compile/ProjectCopyFile-stderr.txt new file mode 100644 index 0000000..45241c9 --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectCopyFile-stderr.txt @@ -0,0 +1,7 @@ +CMake Warning \(dev\) at ProjectCopyFile.cmake:[0-9]+ \(try_compile\): + Unknown arguments: + + "COPY_FILE" + "result" +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/ProjectCopyFile.cmake b/Tests/RunCMake/try_compile/ProjectCopyFile.cmake new file mode 100644 index 0000000..6bfec99 --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectCopyFile.cmake @@ -0,0 +1,4 @@ +try_compile(RESULT + PROJECT TestProject + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/proj + COPY_FILE result) diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-result.txt b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-stderr.txt b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-stderr.txt new file mode 100644 index 0000000..dc6f354 --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at ProjectSrcDirEmpty.cmake:[0-9]+ \(try_compile\): + No <srcdir> specified. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirEmpty.cmake b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty.cmake new file mode 100644 index 0000000..ac33ed0 --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectSrcDirEmpty.cmake @@ -0,0 +1 @@ +try_compile(RESULT PROJECT Foo SOURCE_DIR "") diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirMissing-result.txt b/Tests/RunCMake/try_compile/ProjectSrcDirMissing-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectSrcDirMissing-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirMissing-stderr.txt b/Tests/RunCMake/try_compile/ProjectSrcDirMissing-stderr.txt new file mode 100644 index 0000000..af6edd5 --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectSrcDirMissing-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at ProjectSrcDirMissing.cmake:[0-9]+ \(try_compile\): + No <srcdir> specified. +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/ProjectSrcDirMissing.cmake b/Tests/RunCMake/try_compile/ProjectSrcDirMissing.cmake new file mode 100644 index 0000000..e32cdf4 --- /dev/null +++ b/Tests/RunCMake/try_compile/ProjectSrcDirMissing.cmake @@ -0,0 +1 @@ +try_compile(RESULT PROJECT Foo) diff --git a/Tests/RunCMake/try_compile/RunCMakeTest.cmake b/Tests/RunCMake/try_compile/RunCMakeTest.cmake index fb4b836..a3a3451 100644 --- a/Tests/RunCMake/try_compile/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_compile/RunCMakeTest.cmake @@ -1,32 +1,39 @@ include(RunCMake) -run_cmake(CopyFileErrorNoCopyFile) run_cmake(NoArgs) run_cmake(OneArg) run_cmake(TwoArgs) -run_cmake(NoCopyFile) -run_cmake(NoCopyFile2) -run_cmake(NoCopyFileError) -run_cmake(NoOutputVariable) -run_cmake(NoOutputVariable2) run_cmake(NoSources) -run_cmake(BadLinkLibraries) -run_cmake(BadSources1) -run_cmake(BadSources2) +run_cmake(BinDirEmpty) +run_cmake(BinDirRelative) +run_cmake(ProjectSrcDirMissing) +run_cmake(ProjectSrcDirEmpty) +run_cmake(ProjectBinDirEmpty) +run_cmake(OldProjectSrcDirEmpty) +run_cmake(OldProjectBinDirEmpty) + +set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=old_signature.cmake) +include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=new_signature.cmake) +include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake) +unset(RunCMake_TEST_OPTIONS) + +run_cmake(SourceFromOneArg) +run_cmake(SourceFromThreeArgs) +run_cmake(SourceFromBadName) +run_cmake(SourceFromBadFile) + +run_cmake(ProjectCopyFile) run_cmake(NonSourceCopyFile) run_cmake(NonSourceCompileDefinitions) -run_cmake(EnvConfig) - set(RunCMake_TEST_OPTIONS --debug-trycompile) run_cmake(PlatformVariables) run_cmake(WarnDeprecated) unset(RunCMake_TEST_OPTIONS) -run_cmake(TargetTypeExe) -run_cmake(TargetTypeInvalid) -run_cmake(TargetTypeStatic) - if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND CMAKE_C_COMPILER_ID MATCHES "^(MSVC|GNU|LCC|Clang|AppleClang)$") set (RunCMake_TEST_OPTIONS -DRunCMake_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}) @@ -34,41 +41,6 @@ if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND unset (RunCMake_TEST_OPTIONS) endif() -if(CMAKE_C_STANDARD_DEFAULT) - run_cmake(CStandard) -elseif(DEFINED CMAKE_C_STANDARD_DEFAULT) - run_cmake(CStandardNoDefault) -endif() -if(CMAKE_OBJC_STANDARD_DEFAULT) - run_cmake(ObjCStandard) -endif() -if(CMAKE_CXX_STANDARD_DEFAULT) - run_cmake(CxxStandard) -elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT) - run_cmake(CxxStandardNoDefault) -endif() -if(CMAKE_OBJCXX_STANDARD_DEFAULT) - run_cmake(ObjCxxStandard) -endif() -if(CMake_TEST_CUDA) - run_cmake(CudaStandard) -endif() -if(CMake_TEST_ISPC) - run_cmake(ISPCTargets) - run_cmake(ISPCInvalidTarget) - set(ninja "") - if(RunCMake_GENERATOR MATCHES "Ninja") - set(ninja "Ninja") - endif() - run_cmake(ISPCDuplicateTarget${ninja}) -endif() -if((CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) OR CMAKE_C_COMPILER_ID MATCHES "LCC") - run_cmake(CStandardGNU) -endif() -if((CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) OR CMAKE_C_COMPILER_ID MATCHES "LCC") - run_cmake(CxxStandardGNU) -endif() - run_cmake(CMP0056) run_cmake(CMP0066) run_cmake(CMP0067) diff --git a/Tests/RunCMake/try_compile/SourceFromBadFile-result.txt b/Tests/RunCMake/try_compile/SourceFromBadFile-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromBadFile-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt b/Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt new file mode 100644 index 0000000..53a6d8d --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromBadFile-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at SourceFromBadFile.cmake:[0-9]+ \(try_compile\): + SOURCE_FROM_FILE failed to copy "bad#source.c": No such file or directory +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/SourceFromBadFile.cmake b/Tests/RunCMake/try_compile/SourceFromBadFile.cmake new file mode 100644 index 0000000..0a37f11 --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromBadFile.cmake @@ -0,0 +1 @@ +try_compile(RESULT SOURCE_FROM_FILE bad.c "bad#source.c") diff --git a/Tests/RunCMake/try_compile/SourceFromBadName-result.txt b/Tests/RunCMake/try_compile/SourceFromBadName-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromBadName-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/SourceFromBadName-stderr.txt b/Tests/RunCMake/try_compile/SourceFromBadName-stderr.txt new file mode 100644 index 0000000..041f3f1 --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromBadName-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at SourceFromBadName.cmake:[0-9]+ \(try_compile\): + SOURCE_FROM_CONTENT given invalid filename "bad/name.c" +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/SourceFromBadName.cmake b/Tests/RunCMake/try_compile/SourceFromBadName.cmake new file mode 100644 index 0000000..44d92fd --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromBadName.cmake @@ -0,0 +1 @@ +try_compile(RESULT SOURCE_FROM_CONTENT bad/name.c "int main();") diff --git a/Tests/RunCMake/try_compile/SourceFromOneArg-result.txt b/Tests/RunCMake/try_compile/SourceFromOneArg-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromOneArg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/SourceFromOneArg-stderr.txt b/Tests/RunCMake/try_compile/SourceFromOneArg-stderr.txt new file mode 100644 index 0000000..8b2248a --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromOneArg-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at SourceFromOneArg.cmake:[0-9]+ \(try_compile\): + SOURCE_FROM_CONTENT requires exactly two arguments +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/SourceFromOneArg.cmake b/Tests/RunCMake/try_compile/SourceFromOneArg.cmake new file mode 100644 index 0000000..5a50499 --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromOneArg.cmake @@ -0,0 +1 @@ +try_compile(RESULT SOURCE_FROM_CONTENT test.c) diff --git a/Tests/RunCMake/try_compile/SourceFromThreeArgs-result.txt b/Tests/RunCMake/try_compile/SourceFromThreeArgs-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromThreeArgs-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_compile/SourceFromThreeArgs-stderr.txt b/Tests/RunCMake/try_compile/SourceFromThreeArgs-stderr.txt new file mode 100644 index 0000000..5f2ff61 --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromThreeArgs-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at SourceFromThreeArgs.cmake:[0-9]+ \(try_compile\): + SOURCE_FROM_CONTENT requires exactly two arguments +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/SourceFromThreeArgs.cmake b/Tests/RunCMake/try_compile/SourceFromThreeArgs.cmake new file mode 100644 index 0000000..196851a --- /dev/null +++ b/Tests/RunCMake/try_compile/SourceFromThreeArgs.cmake @@ -0,0 +1 @@ +try_compile(RESULT SOURCE_FROM_CONTENT test.c "int" "main();") diff --git a/Tests/RunCMake/try_compile/TargetTypeExe.cmake b/Tests/RunCMake/try_compile/TargetTypeExe.cmake index 9b6e727..330f5f5 100644 --- a/Tests/RunCMake/try_compile/TargetTypeExe.cmake +++ b/Tests/RunCMake/try_compile/TargetTypeExe.cmake @@ -1,14 +1,20 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(C) + set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src.c + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/src.c OUTPUT_VARIABLE out COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copy COPY_FILE_ERROR copy_err ) + if(NOT result) message(FATAL_ERROR "try_compile failed:\n${out}") endif() + if(copy_err) message(FATAL_ERROR "try_compile COPY_FILE failed:\n${copy_err}") endif() diff --git a/Tests/RunCMake/try_compile/TargetTypeInvalid-stderr.txt b/Tests/RunCMake/try_compile/TargetTypeInvalid-stderr.txt index 08b281a..e9123e3 100644 --- a/Tests/RunCMake/try_compile/TargetTypeInvalid-stderr.txt +++ b/Tests/RunCMake/try_compile/TargetTypeInvalid-stderr.txt @@ -1,4 +1,4 @@ -^CMake Error at TargetTypeInvalid.cmake:2 \(try_compile\): +^CMake Error at TargetTypeInvalid.cmake:[0-9]+ \(try_compile\): Invalid value 'INVALID' for CMAKE_TRY_COMPILE_TARGET_TYPE. Only 'EXECUTABLE' and 'STATIC_LIBRARY' are allowed. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/try_compile/TargetTypeInvalid.cmake b/Tests/RunCMake/try_compile/TargetTypeInvalid.cmake index 0bbc4ac..15a20bb 100644 --- a/Tests/RunCMake/try_compile/TargetTypeInvalid.cmake +++ b/Tests/RunCMake/try_compile/TargetTypeInvalid.cmake @@ -1,2 +1,6 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + set(CMAKE_TRY_COMPILE_TARGET_TYPE INVALID) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src.c) + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c) diff --git a/Tests/RunCMake/try_compile/TargetTypeStatic.cmake b/Tests/RunCMake/try_compile/TargetTypeStatic.cmake index 006b8b8..98dea41 100644 --- a/Tests/RunCMake/try_compile/TargetTypeStatic.cmake +++ b/Tests/RunCMake/try_compile/TargetTypeStatic.cmake @@ -1,14 +1,20 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + enable_language(C) + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -try_compile(result ${CMAKE_CURRENT_BINARY_DIR} - SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/other.c + +try_compile(result ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/other.c OUTPUT_VARIABLE out COPY_FILE ${CMAKE_CURRENT_BINARY_DIR}/copy COPY_FILE_ERROR copy_err ) + if(NOT result) message(FATAL_ERROR "try_compile failed:\n${out}") endif() + if(copy_err) message(FATAL_ERROR "try_compile COPY_FILE failed:\n${copy_err}") endif() diff --git a/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt b/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt new file mode 100644 index 0000000..2a58e71 --- /dev/null +++ b/Tests/RunCMake/try_compile/TryRunArgs-stderr.txt @@ -0,0 +1,18 @@ +^CMake Warning \(dev\) at TryRunArgs.cmake:[0-9]+ \(try_compile\): + Unknown arguments: + + "COMPILE_OUTPUT_VARIABLE" + "compOutputVar" + "RUN_OUTPUT_VARIABLE" + "runOutputVar" + "RUN_OUTPUT_STDOUT_VARIABLE" + "runOutputStdOutVar" + "RUN_OUTPUT_STDERR_VARIABLE" + "runOutputStdErrVar" + "WORKING_DIRECTORY" + "runWorkDir" + "ARGS" + "runArgs" +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/try_compile/TryRunArgs.cmake b/Tests/RunCMake/try_compile/TryRunArgs.cmake new file mode 100644 index 0000000..e4cb1fe --- /dev/null +++ b/Tests/RunCMake/try_compile/TryRunArgs.cmake @@ -0,0 +1,14 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + +enable_language(C) + +try_compile(RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COPY_FILE "${CMAKE_CURRENT_BINARY_DIR}/out.bin" + COMPILE_OUTPUT_VARIABLE compOutputVar + RUN_OUTPUT_VARIABLE runOutputVar + RUN_OUTPUT_STDOUT_VARIABLE runOutputStdOutVar + RUN_OUTPUT_STDERR_VARIABLE runOutputStdErrVar + WORKING_DIRECTORY runWorkDir + ARGS runArgs + ) diff --git a/Tests/RunCMake/try_compile/TwoArgs-stderr.txt b/Tests/RunCMake/try_compile/TwoArgs-stderr.txt index b9c08fc..b68e78e 100644 --- a/Tests/RunCMake/try_compile/TwoArgs-stderr.txt +++ b/Tests/RunCMake/try_compile/TwoArgs-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at TwoArgs.cmake:1 \(try_compile\): - try_compile unknown error. +CMake Error at TwoArgs.cmake:[0-9]+ \(try_compile\): + The try_compile\(\) command requires at least 3 arguments. Call Stack \(most recent call first\): CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt b/Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt new file mode 100644 index 0000000..6474990 --- /dev/null +++ b/Tests/RunCMake/try_compile/WarnDeprecated-stderr.txt @@ -0,0 +1,11 @@ +^CMake Debug Log at [^ +]*/Modules/CMakeDetermineCompilerABI.cmake:[0-9]+ \(try_compile\): + Executing try_compile \(CMAKE_C_ABI_COMPILED\) in: + + [^ +]*/Tests/RunCMake/try_compile/WarnDeprecated-build/CMakeFiles/CMakeScratch/TryCompile-[^/]+ +Call Stack \(most recent call first\): + [^ +]*/Modules/CMakeTestCCompiler.cmake:[0-9]+ \(CMAKE_DETERMINE_COMPILER_ABI\) + WarnDeprecated.cmake:[0-9]+ \(enable_language\) + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/try_compile/new_signature.cmake b/Tests/RunCMake/try_compile/new_signature.cmake new file mode 100644 index 0000000..cbcb261 --- /dev/null +++ b/Tests/RunCMake/try_compile/new_signature.cmake @@ -0,0 +1,2 @@ +set(try_compile_bindir_or_SOURCES SOURCES) +set(try_compile_redundant_SOURCES "") diff --git a/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake b/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake new file mode 100644 index 0000000..ac07ad3 --- /dev/null +++ b/Tests/RunCMake/try_compile/old_and_new_signature_tests.cmake @@ -0,0 +1,66 @@ +# These tests are performed using both the historic and the newer SOURCES +# signatures of try_compile. It is critical that they behave the same and +# produce comparable output for both signatures. Tests that cannot do this +# belong in RunCMakeTests.txt, not here. +# +# Tests here MUST include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) and +# use the variables defined therein appropriately. Refer to existing tests for +# examples. + +run_cmake(CopyFileErrorNoCopyFile) +run_cmake(NoCopyFile) +run_cmake(NoCopyFile2) +run_cmake(NoCopyFileError) +run_cmake(NoCStandard) +run_cmake(NoOutputVariable) +run_cmake(NoOutputVariable2) +run_cmake(BadLinkLibraries) +run_cmake(BadSources1) +run_cmake(BadSources2) +run_cmake(EmptyValueArgs) +run_cmake(EmptyListArgs) +run_cmake(TryRunArgs) +run_cmake(BuildType) +run_cmake(BuildTypeAsFlag) +run_cmake(OutputDirAsFlag) + +run_cmake(EnvConfig) + +run_cmake(TargetTypeExe) +run_cmake(TargetTypeInvalid) +run_cmake(TargetTypeStatic) + +if(CMAKE_C_STANDARD_DEFAULT) + run_cmake(CStandard) +elseif(DEFINED CMAKE_C_STANDARD_DEFAULT) + run_cmake(CStandardNoDefault) +endif() +if(CMAKE_OBJC_STANDARD_DEFAULT) + run_cmake(ObjCStandard) +endif() +if(CMAKE_CXX_STANDARD_DEFAULT) + run_cmake(CxxStandard) +elseif(DEFINED CMAKE_CXX_STANDARD_DEFAULT) + run_cmake(CxxStandardNoDefault) +endif() +if(CMAKE_OBJCXX_STANDARD_DEFAULT) + run_cmake(ObjCxxStandard) +endif() +if(CMake_TEST_CUDA) + run_cmake(CudaStandard) +endif() +if(CMake_TEST_ISPC) + run_cmake(ISPCTargets) + run_cmake(ISPCInvalidTarget) + set(ninja "") + if(RunCMake_GENERATOR MATCHES "Ninja") + set(ninja "Ninja") + endif() + run_cmake(ISPCDuplicateTarget${ninja}) +endif() +if((CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.4) OR CMAKE_C_COMPILER_ID MATCHES "LCC") + run_cmake(CStandardGNU) +endif() +if((CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) OR CMAKE_C_COMPILER_ID MATCHES "LCC") + run_cmake(CxxStandardGNU) +endif() diff --git a/Tests/RunCMake/try_compile/old_signature.cmake b/Tests/RunCMake/try_compile/old_signature.cmake new file mode 100644 index 0000000..94b12de --- /dev/null +++ b/Tests/RunCMake/try_compile/old_signature.cmake @@ -0,0 +1,2 @@ +set(try_compile_bindir_or_SOURCES ${CMAKE_CURRENT_BINARY_DIR}) +set(try_compile_redundant_SOURCES SOURCES) diff --git a/Tests/RunCMake/try_run/BadLinkLibraries-stderr.txt b/Tests/RunCMake/try_run/BadLinkLibraries-stderr.txt index dcd1bfc..f9cc50e 100644 --- a/Tests/RunCMake/try_run/BadLinkLibraries-stderr.txt +++ b/Tests/RunCMake/try_run/BadLinkLibraries-stderr.txt @@ -1,4 +1,4 @@ -CMake Error at BadLinkLibraries.cmake:2 \(try_run\): +CMake Error at BadLinkLibraries.cmake:[0-9+] \(try_run\): Only libraries may be used as try_compile or try_run IMPORTED LINK_LIBRARIES. Got not_a_library of type UTILITY. Call Stack \(most recent call first\): diff --git a/Tests/RunCMake/try_run/BadLinkLibraries.cmake b/Tests/RunCMake/try_run/BadLinkLibraries.cmake index a124bf6..950a942 100644 --- a/Tests/RunCMake/try_run/BadLinkLibraries.cmake +++ b/Tests/RunCMake/try_run/BadLinkLibraries.cmake @@ -1,4 +1,7 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + add_custom_target(not_a_library) -try_run(RUN_RESULT COMPILE_RESULT - ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp ${CMAKE_CURRENT_SOURCE_DIR}/src.c + +try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c LINK_LIBRARIES not_a_library) diff --git a/Tests/RunCMake/try_run/BinDirEmpty-result.txt b/Tests/RunCMake/try_run/BinDirEmpty-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_run/BinDirEmpty-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_run/BinDirEmpty-stderr.txt b/Tests/RunCMake/try_run/BinDirEmpty-stderr.txt new file mode 100644 index 0000000..def1c22 --- /dev/null +++ b/Tests/RunCMake/try_run/BinDirEmpty-stderr.txt @@ -0,0 +1,4 @@ +^CMake Error at BinDirEmpty.cmake:[0-9]+ \(try_run\): + No <bindir> specified. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_run/BinDirEmpty.cmake b/Tests/RunCMake/try_run/BinDirEmpty.cmake new file mode 100644 index 0000000..d4b7ee3 --- /dev/null +++ b/Tests/RunCMake/try_run/BinDirEmpty.cmake @@ -0,0 +1 @@ +try_run(runResultVar compileResultVar "" ${CMAKE_CURRENT_SOURCE_DIR}/src.c) diff --git a/Tests/RunCMake/try_run/BinDirRelative-result.txt b/Tests/RunCMake/try_run/BinDirRelative-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_run/BinDirRelative-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_run/BinDirRelative-stderr.txt b/Tests/RunCMake/try_run/BinDirRelative-stderr.txt new file mode 100644 index 0000000..54d4e86 --- /dev/null +++ b/Tests/RunCMake/try_run/BinDirRelative-stderr.txt @@ -0,0 +1,6 @@ +^CMake Error at BinDirRelative.cmake:[0-9]+ \(try_run\): + <bindir> is not an absolute path: + + 'bin_dir_relative' +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_run/BinDirRelative.cmake b/Tests/RunCMake/try_run/BinDirRelative.cmake new file mode 100644 index 0000000..a277403 --- /dev/null +++ b/Tests/RunCMake/try_run/BinDirRelative.cmake @@ -0,0 +1 @@ +try_run(runResultVar compileResultVar bin_dir_relative ${CMAKE_CURRENT_SOURCE_DIR}/src.c) diff --git a/Tests/RunCMake/try_run/NoCompileOutputVariable-result.txt b/Tests/RunCMake/try_run/NoCompileOutputVariable-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_run/NoCompileOutputVariable-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt b/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt new file mode 100644 index 0000000..e8baffb --- /dev/null +++ b/Tests/RunCMake/try_run/NoCompileOutputVariable-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at NoCompileOutputVariable.cmake:[0-9]+ \(try_run\): + Error after keyword "COMPILE_OUTPUT_VARIABLE": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_run/NoCompileOutputVariable.cmake b/Tests/RunCMake/try_run/NoCompileOutputVariable.cmake new file mode 100644 index 0000000..9eb7c5e --- /dev/null +++ b/Tests/RunCMake/try_run/NoCompileOutputVariable.cmake @@ -0,0 +1,6 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + +try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + COMPILE_OUTPUT_VARIABLE + ) diff --git a/Tests/RunCMake/try_run/NoOutputCompileVariable-result.txt b/Tests/RunCMake/try_run/NoOutputCompileVariable-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_run/NoOutputCompileVariable-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_run/NoOutputVariable-result.txt b/Tests/RunCMake/try_run/NoOutputVariable-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_run/NoOutputVariable-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt b/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt new file mode 100644 index 0000000..46cfca0 --- /dev/null +++ b/Tests/RunCMake/try_run/NoOutputVariable-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at NoOutputVariable.cmake:[0-9]+ \(try_run\): + Error after keyword "OUTPUT_VARIABLE": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_run/NoOutputVariable.cmake b/Tests/RunCMake/try_run/NoOutputVariable.cmake new file mode 100644 index 0000000..1901b30 --- /dev/null +++ b/Tests/RunCMake/try_run/NoOutputVariable.cmake @@ -0,0 +1,4 @@ +try_run(RUN_RESULT COMPILE_RESULT + ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp ${CMAKE_CURRENT_SOURCE_DIR}/src.c + OUTPUT_VARIABLE + ) diff --git a/Tests/RunCMake/try_run/NoRunOutputVariable-result.txt b/Tests/RunCMake/try_run/NoRunOutputVariable-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_run/NoRunOutputVariable-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt b/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt new file mode 100644 index 0000000..8ccbdab --- /dev/null +++ b/Tests/RunCMake/try_run/NoRunOutputVariable-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at NoRunOutputVariable.cmake:[0-9]+ \(try_run\): + Error after keyword "RUN_OUTPUT_VARIABLE": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_run/NoRunOutputVariable.cmake b/Tests/RunCMake/try_run/NoRunOutputVariable.cmake new file mode 100644 index 0000000..f9e5e0b --- /dev/null +++ b/Tests/RunCMake/try_run/NoRunOutputVariable.cmake @@ -0,0 +1,6 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + +try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + RUN_OUTPUT_VARIABLE + ) diff --git a/Tests/RunCMake/try_run/NoRunStdErrVariable-result.txt b/Tests/RunCMake/try_run/NoRunStdErrVariable-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_run/NoRunStdErrVariable-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt b/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt new file mode 100644 index 0000000..1443ab2 --- /dev/null +++ b/Tests/RunCMake/try_run/NoRunStdErrVariable-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at NoRunStdErrVariable.cmake:[0-9]+ \(try_run\): + Error after keyword "RUN_OUTPUT_STDERR_VARIABLE": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/try_run/NoRunStdErrVariable.cmake b/Tests/RunCMake/try_run/NoRunStdErrVariable.cmake new file mode 100644 index 0000000..888bc25 --- /dev/null +++ b/Tests/RunCMake/try_run/NoRunStdErrVariable.cmake @@ -0,0 +1,7 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + +try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/workdir + RUN_OUTPUT_STDERR_VARIABLE + ) diff --git a/Tests/RunCMake/try_run/NoRunStdOutVariable-result.txt b/Tests/RunCMake/try_run/NoRunStdOutVariable-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_run/NoRunStdOutVariable-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt b/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt new file mode 100644 index 0000000..8b90e94 --- /dev/null +++ b/Tests/RunCMake/try_run/NoRunStdOutVariable-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at NoRunStdOutVariable.cmake:[0-9]+ \(try_run\): + Error after keyword "RUN_OUTPUT_STDOUT_VARIABLE": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/try_run/NoRunStdOutVariable.cmake b/Tests/RunCMake/try_run/NoRunStdOutVariable.cmake new file mode 100644 index 0000000..ed6ab88 --- /dev/null +++ b/Tests/RunCMake/try_run/NoRunStdOutVariable.cmake @@ -0,0 +1,7 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + +try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/workdir + RUN_OUTPUT_STDOUT_VARIABLE + ) diff --git a/Tests/RunCMake/try_run/NoWorkingDirectory-result.txt b/Tests/RunCMake/try_run/NoWorkingDirectory-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/try_run/NoWorkingDirectory-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt b/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt new file mode 100644 index 0000000..b6e258f --- /dev/null +++ b/Tests/RunCMake/try_run/NoWorkingDirectory-stderr.txt @@ -0,0 +1,7 @@ +^CMake Error at NoWorkingDirectory.cmake:[0-9]+ \(try_run\): + Error after keyword "WORKING_DIRECTORY": + + missing required value + +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\)$ diff --git a/Tests/RunCMake/try_run/NoWorkingDirectory.cmake b/Tests/RunCMake/try_run/NoWorkingDirectory.cmake new file mode 100644 index 0000000..0d68182 --- /dev/null +++ b/Tests/RunCMake/try_run/NoWorkingDirectory.cmake @@ -0,0 +1,6 @@ +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + +try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + WORKING_DIRECTORY + ) diff --git a/Tests/RunCMake/try_run/RunCMakeTest.cmake b/Tests/RunCMake/try_run/RunCMakeTest.cmake index d74add0..dbea089 100644 --- a/Tests/RunCMake/try_run/RunCMakeTest.cmake +++ b/Tests/RunCMake/try_run/RunCMakeTest.cmake @@ -1,6 +1,16 @@ include(RunCMake) -run_cmake(BadLinkLibraries) +run_cmake(BinDirEmpty) +run_cmake(BinDirRelative) +run_cmake(NoOutputVariable) + +set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=old_signature.cmake) +include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake) +unset(RunCMake_TEST_OPTIONS) + +set(RunCMake_TEST_OPTIONS -Dtry_compile_DEFS=new_signature.cmake) +include(${RunCMake_SOURCE_DIR}/old_and_new_signature_tests.cmake) +unset(RunCMake_TEST_OPTIONS) if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND CMAKE_C_COMPILER_ID MATCHES "^(MSVC|GNU|LCC|Clang|AppleClang)$") @@ -8,5 +18,3 @@ if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$" AND run_cmake(LinkOptions) unset (RunCMake_TEST_OPTIONS) endif() - -run_cmake(WorkingDirArg) diff --git a/Tests/RunCMake/try_run/WorkingDirArg.cmake b/Tests/RunCMake/try_run/WorkingDirArg.cmake index b583823..375a703 100644 --- a/Tests/RunCMake/try_run/WorkingDirArg.cmake +++ b/Tests/RunCMake/try_run/WorkingDirArg.cmake @@ -1,6 +1,8 @@ -try_run(RUN_RESULT COMPILE_RESULT - ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp ${CMAKE_CURRENT_SOURCE_DIR}/src.c - RUN_OUTPUT_VARIABLE OUTPUT_VARIABLE +include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) + +try_run(RUN_RESULT COMPILE_RESULT ${try_compile_bindir_or_SOURCES} + ${CMAKE_CURRENT_SOURCE_DIR}/src.c + RUN_OUTPUT_VARIABLE RUN_OUTPUT WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp/workdir ) diff --git a/Tests/RunCMake/try_run/new_signature.cmake b/Tests/RunCMake/try_run/new_signature.cmake new file mode 100644 index 0000000..cbcb261 --- /dev/null +++ b/Tests/RunCMake/try_run/new_signature.cmake @@ -0,0 +1,2 @@ +set(try_compile_bindir_or_SOURCES SOURCES) +set(try_compile_redundant_SOURCES "") diff --git a/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake b/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake new file mode 100644 index 0000000..e1c1784 --- /dev/null +++ b/Tests/RunCMake/try_run/old_and_new_signature_tests.cmake @@ -0,0 +1,20 @@ +# These tests are performed using both the historic and the newer SOURCES +# signatures of try_run. It is critical that they behave the same and produce +# comparable output for both signatures. Tests that cannot do this belong in +# RunCMakeTests.txt, not here. +# +# Tests here MUST include(${CMAKE_CURRENT_SOURCE_DIR}/${try_compile_DEFS}) and +# use the variables defined therein appropriately. Refer to existing tests for +# examples. + +run_cmake(BadLinkLibraries) +run_cmake(BinDirEmpty) +run_cmake(BinDirRelative) + +run_cmake(WorkingDirArg) + +run_cmake(NoCompileOutputVariable) +run_cmake(NoRunOutputVariable) +run_cmake(NoRunStdOutVariable) +run_cmake(NoRunStdErrVariable) +run_cmake(NoWorkingDirectory) diff --git a/Tests/RunCMake/try_run/old_signature.cmake b/Tests/RunCMake/try_run/old_signature.cmake new file mode 100644 index 0000000..94b12de --- /dev/null +++ b/Tests/RunCMake/try_run/old_signature.cmake @@ -0,0 +1,2 @@ +set(try_compile_bindir_or_SOURCES ${CMAKE_CURRENT_BINARY_DIR}) +set(try_compile_redundant_SOURCES SOURCES) diff --git a/Tests/SwiftMixLib/CMakeLists.txt b/Tests/SwiftMixLib/CMakeLists.txt new file mode 100644 index 0000000..40d3498 --- /dev/null +++ b/Tests/SwiftMixLib/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.24) +project(SwiftMixLib C CXX Swift) + +add_library(SwiftMixedLib lib.c lib.cpp lib.swift) +add_executable(Swifty main.swift) +target_link_libraries(Swifty PUBLIC SwiftMixedLib) diff --git a/Tests/SwiftMixLib/lib.c b/Tests/SwiftMixLib/lib.c new file mode 100644 index 0000000..8eca512 --- /dev/null +++ b/Tests/SwiftMixLib/lib.c @@ -0,0 +1,4 @@ +int add_int(int a, int b) +{ + return a + b; +} diff --git a/Tests/SwiftMixLib/lib.cpp b/Tests/SwiftMixLib/lib.cpp new file mode 100644 index 0000000..3e156b8 --- /dev/null +++ b/Tests/SwiftMixLib/lib.cpp @@ -0,0 +1,4 @@ +int add(int a, int b) +{ + return a + b; +} diff --git a/Tests/SwiftMixLib/lib.swift b/Tests/SwiftMixLib/lib.swift new file mode 100644 index 0000000..61009d8 --- /dev/null +++ b/Tests/SwiftMixLib/lib.swift @@ -0,0 +1,3 @@ +public func add(a: Int, b: Int) -> Int { + a + b +} diff --git a/Tests/SwiftMixLib/main.swift b/Tests/SwiftMixLib/main.swift new file mode 100644 index 0000000..d2e9364 --- /dev/null +++ b/Tests/SwiftMixLib/main.swift @@ -0,0 +1,3 @@ +import SwiftMixedLib + +print(add(a: 1, b: 2)) diff --git a/Tests/SwiftOnly/CMakeLists.txt b/Tests/SwiftOnly/CMakeLists.txt index 01c2222..e92e544 100644 --- a/Tests/SwiftOnly/CMakeLists.txt +++ b/Tests/SwiftOnly/CMakeLists.txt @@ -25,6 +25,7 @@ endif() set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift) add_executable(SwiftOnly main.swift) +target_compile_definitions(SwiftOnly PRIVATE SWIFTONLY) add_library(L L.swift) diff --git a/Tests/SwiftOnly/main.swift b/Tests/SwiftOnly/main.swift index 28560d0..a3f1a2c 100644 --- a/Tests/SwiftOnly/main.swift +++ b/Tests/SwiftOnly/main.swift @@ -1 +1,7 @@ dump("SwiftOnly") + +#if SWIFTONLY +dump("SWIFTONLY defined") +#else +fatalError("SWIFTONLY NOT defined") +#endif diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt index 000fd2c..3e46ed5 100644 --- a/Tests/TryCompile/CMakeLists.txt +++ b/Tests/TryCompile/CMakeLists.txt @@ -4,163 +4,96 @@ if(POLICY CMP0129) endif() project(TryCompile) -macro(TEST_ASSERT value msg) - if (NOT ${value}) - message (SEND_ERROR "Assertion failure:" ${msg} ) - endif () +macro(EXPECT_PASS var out) + if(NOT ${var}) + message(SEND_ERROR "Should pass failed:\n${out}") + endif() endmacro() -macro(TEST_FAIL value msg) - if (${value}) - message (SEND_ERROR "Failing test succeeded:" ${msg} ) - endif () +macro(EXPECT_FAIL var out) + if(${var}) + message(SEND_ERROR "Should fail passed:\n${out}") + endif() endmacro() -macro(TEST_EXPECT_EXACT command expected) - if(NOT "x${result}" STREQUAL "x${expected}") - message(SEND_ERROR "${CMAKE_CURRENT_LIST_LINE}: TEST \"${command}\" failed: \"${result}\" expected: \"${expected}\"") +macro(EXPECT_COMPILED name var out) + if(NOT ${var}) + message(SEND_ERROR "${name} failed compiling:\n${out}") endif() endmacro() -macro(TEST_EXPECT_CONTAINS command expected) - if(NOT "${result}" MATCHES "${expected}") - message(SEND_ERROR "${CMAKE_CURRENT_LIST_LINE}: TEST \"${command}\" failed: \"${result}\" expected: \"${expected}\"") +macro(EXPECT_RUN_RESULT name var expected) + if(NOT ${var} EQUAL ${expected}) + message(SEND_ERROR " ${name} gave unexpected run result: ${${var}} expected: ${expected}") endif() endmacro() +macro(TEST_ASSERT value msg) + if (NOT ${value}) + message (SEND_ERROR "Assertion failure:" ${msg} ) + endif () +endmacro() -# try to compile a file that should compile -# also check that COPY_FILE works -try_compile(SHOULD_PASS - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/pass.c - OUTPUT_VARIABLE TRY_OUT - COPY_FILE ${TryCompile_BINARY_DIR}/CopyOfPass - ) - -if(NOT SHOULD_PASS) - message(SEND_ERROR "should pass failed ${TRY_OUT}") -endif() -if(NOT EXISTS "${TryCompile_BINARY_DIR}/CopyOfPass") - message(SEND_ERROR "COPY_FILE to \"${TryCompile_BINARY_DIR}/CopyOfPass\" failed") -else() - file(REMOVE "${TryCompile_BINARY_DIR}/CopyOfPass") -endif() - -# try to compile a file that should compile -# also check that COPY_FILE_ERROR works -file(WRITE ${TryCompile_BINARY_DIR}/invalid "") -try_compile(SHOULD_PASS - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/pass.c - OUTPUT_VARIABLE TRY_OUT - COPY_FILE ${TryCompile_BINARY_DIR}/invalid/path - COPY_FILE_ERROR _captured - ) -if(NOT SHOULD_PASS) - message(SEND_ERROR "should pass failed ${TRY_OUT}") -endif() -if(NOT _captured MATCHES "Cannot copy output executable.*/invalid/path") - message(SEND_ERROR "COPY_FILE_ERROR did not capture expected message") -endif() - -# try to compile a file that should not compile -try_compile(SHOULD_FAIL - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/fail.c - OUTPUT_VARIABLE TRY_OUT) -if(SHOULD_FAIL) - message(SEND_ERROR "Should fail passed ${TRY_OUT}") -endif() - -# try to compile a file that should compile -try_compile(SHOULD_PASS - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/pass.c - OUTPUT_VARIABLE TRY_OUT) -if(NOT SHOULD_PASS) - message(SEND_ERROR "should pass failed ${TRY_OUT}") -endif() - -# try to compile a file that should not compile -try_compile(SHOULD_FAIL - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/fail.c - OUTPUT_VARIABLE TRY_OUT) -if(SHOULD_FAIL) - message(SEND_ERROR "Should fail passed ${TRY_OUT}") -endif() - -# try to compile two files that should compile -try_compile(SHOULD_PASS - ${TryCompile_BINARY_DIR} - SOURCES ${TryCompile_SOURCE_DIR}/pass2a.c ${TryCompile_SOURCE_DIR}/pass2b.cxx - OUTPUT_VARIABLE TRY_OUT) -if(NOT SHOULD_PASS) - message(SEND_ERROR "should pass failed ${TRY_OUT}") -endif() - -# try to compile two files that should not compile -try_compile(SHOULD_FAIL - ${TryCompile_BINARY_DIR} - SOURCES ${TryCompile_SOURCE_DIR}/fail2a.c ${TryCompile_SOURCE_DIR}/fail2b.c - OUTPUT_VARIABLE TRY_OUT) -if(SHOULD_FAIL) - message(SEND_ERROR "Should fail passed ${TRY_OUT}") -endif() - -# try to compile a file that should compile -set(_c_flags "${CMAKE_C_FLAGS}") -if(WATCOM) - string(APPEND CMAKE_C_FLAGS " -dTESTDEF") -else() - string(APPEND CMAKE_C_FLAGS " \"-DTESTDEF\"") -endif() +# run old signature tests +set(try_compile_bindir_or_SOURCES ${TryCompile_BINARY_DIR}) +set(try_compile_redundant_SOURCES SOURCES) +set(try_compile_output_vars OUTPUT_VARIABLE TRY_OUT) +set(try_compile_compile_output_var TRY_OUT) +set(try_compile_run_output_var TRY_OUT) +include(old_and_new_signature_tests.cmake) + +# run new signature tests +set(try_compile_bindir_or_SOURCES SOURCES) +set(try_compile_redundant_SOURCES "") +set(try_compile_output_vars + COMPILE_OUTPUT_VARIABLE COMPILE_OUT + RUN_OUTPUT_VARIABLE RUN_OUTPUT) +set(try_compile_compile_output_var COMPILE_OUT) +set(try_compile_run_output_var RUN_OUTPUT) +include(old_and_new_signature_tests.cmake) + +# try to compile an empty source specified directly +try_compile(SHOULD_FAIL_DUE_TO_EMPTY_SOURCE + SOURCE_FROM_CONTENT empty.c "") +if(SHOULD_FAIL_DUE_TO_EMPTY_SOURCE) + message(SEND_ERROR "Trying to compile an empty source succeeded?") +endif() + +try_compile(SHOULD_FAIL_DUE_TO_EMPTY_SOURCE + SOURCE_FROM_VAR empty.c NAME_OF_A_VAR_THAT_IS_NOT_SET) +if(SHOULD_FAIL_DUE_TO_EMPTY_SOURCE) + message(SEND_ERROR "Trying to compile an empty source succeeded?") +endif() + +# try to compile a copied source try_compile(SHOULD_PASS - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/testdef.c - OUTPUT_VARIABLE TRY_OUT) -if(NOT SHOULD_PASS) - message(SEND_ERROR "should pass failed ${TRY_OUT}") -endif() -set(CMAKE_C_FLAGS "${_c_flags}") - -if(NOT SHOULD_FAIL) - if(SHOULD_PASS) - message("All Tests passed, ignore all previous output.") - else() - message("Test failed") - endif() -else() - message("Test failed") -endif() -try_compile(CMAKE_ANSI_FOR_SCOPE - ${TryCompile_BINARY_DIR} - ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUT) -if (CMAKE_ANSI_FOR_SCOPE) - message("Compiler supports ansi for") -else() - message("Compiler does not support ansi for scope") -endif() + SOURCE_FROM_FILE pass.c ${TryCompile_SOURCE_DIR}/pass.c + OUTPUT_VARIABLE TRY_OUT) +EXPECT_COMPILED("SOURCE_FROM_FILE" SHOULD_PASS "${TRY_OUT}") -try_compile(CMAKE_ANSI_FOR_SCOPE - ${TryCompile_BINARY_DIR} - ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUT) -if (CMAKE_ANSI_FOR_SCOPE) - message("Compiler supports ansi for") -else() - message("Compiler does not support ansi for scope") -endif() +# try to run a source specified directly +set(TRY_RUN_MAIN_CODE + "extern int answer(); \n" + "int main() { return answer(); }\n") +set(TRY_RUN_EXT_CODE + "int answer() { return 42; }\n") -message("use the module now") -include(${CMAKE_ROOT}/Modules/TestForANSIForScope.cmake) -if (CMAKE_ANSI_FOR_SCOPE) - message("Compiler supports ansi for") -else() - message("Compiler does not support ansi for scope") -endif() +try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE + SOURCE_FROM_CONTENT main.c "${TRY_RUN_MAIN_CODE}" + SOURCE_FROM_CONTENT answer.c "${TRY_RUN_EXT_CODE}" + COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT) +EXPECT_COMPILED("SOURCE_FROM_CONTENT" SHOULD_COMPILE "${COMPILE_OUTPUT}") +EXPECT_RUN_RESULT("SOURCE_FROM_CONTENT" SHOULD_EXIT_WITH_ERROR 42) -message("Testing try_compile project mode") +try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE + SOURCE_FROM_VAR main.c TRY_RUN_MAIN_CODE + SOURCE_FROM_VAR answer.c TRY_RUN_EXT_CODE + COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT) +EXPECT_COMPILED("SOURCE_FROM_VAR" SHOULD_COMPILE "${COMPILE_OUTPUT}") +EXPECT_RUN_RESULT("SOURCE_FROM_VAR" SHOULD_EXIT_WITH_ERROR 42) + +# try to compile a project (old signature) +message("Testing try_compile project mode (old signature)") try_compile(TEST_INNER ${TryCompile_BINARY_DIR}/CMakeFiles/Inner ${TryCompile_SOURCE_DIR}/Inner @@ -168,241 +101,17 @@ try_compile(TEST_INNER OUTPUT_VARIABLE output) TEST_ASSERT(TEST_INNER "try_compile project mode failed:\n${output}") -try_compile(COMPILE_DEFINITIONS_LIST_EXPANDED - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/check_a_b.c - OUTPUT_VARIABLE output - COMPILE_DEFINITIONS "-DDEF_A;-DDEF_B" - ) -if(COMPILE_DEFINITIONS_LIST_EXPANDED) - message(STATUS "COMPILE_DEFINITIONS list expanded correctly") -else() - string(REPLACE "\n" "\n " output " ${output}") - message(SEND_ERROR "COMPILE_DEFINITIONS list did not expand correctly\n${output}") -endif() - -try_compile(SHOULD_FAIL_DUE_TO_BAD_SOURCE - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/pass.c - OUTPUT_VARIABLE output - COMPILE_DEFINITIONS "bad#source.c" - ) -if(SHOULD_FAIL_DUE_TO_BAD_SOURCE AND NOT CMAKE_GENERATOR MATCHES "Watcom WMake|NMake Makefiles") - string(REPLACE "\n" "\n " output " ${output}") - message(SEND_ERROR "try_compile with bad#source.c did not fail:\n${output}") -elseif(NOT output MATCHES [[(bad#source\.c|bad\.c|bad')]]) - string(REPLACE "\n" "\n " output " ${output}") - message(SEND_ERROR "try_compile with bad#source.c failed without mentioning bad source:\n${output}") -else() - message(STATUS "try_compile with bad#source.c correctly failed") -endif() +# try to compile a project (new signature) +message("Testing try_compile project mode (new signature)") +try_compile(TEST_INNER + PROJECT TryCompileInner + SOURCE_DIR ${TryCompile_SOURCE_DIR}/Inner + TARGET innerexe + OUTPUT_VARIABLE output) +TEST_ASSERT(TEST_INNER "try_compile project mode failed:\n${output}") add_executable(TryCompile pass.c) -###################################### - -# now two tests for try_run() - -# try to run a file that should compile and run without error -# also check that OUTPUT_VARIABLE contains both the compile output -# and the run output -try_run(SHOULD_RUN SHOULD_COMPILE - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/exit_success.c - OUTPUT_VARIABLE TRY_OUT) -if(NOT SHOULD_COMPILE) - message(SEND_ERROR "exit_success failed compiling: ${TRY_OUT}") -endif() -if(NOT "${SHOULD_RUN}" STREQUAL "0") - message(SEND_ERROR "exit_success failed running with exit code ${SHOULD_RUN}") -endif() -# check the compile output for the filename -if(NOT "${TRY_OUT}" MATCHES "exit_success") - message(SEND_ERROR " TRY_OUT didn't contain \"exit_success\": \"${TRY_OUT}\"") -endif() -# check the run output -if(NOT "${TRY_OUT}" MATCHES "hello world") - message(SEND_ERROR " TRY_OUT didn't contain \"hello world\": \"${TRY_OUT}\"") -endif() - -try_run(ARG_TEST_RUN ARG_TEST_COMPILE - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/expect_arg.c - OUTPUT_VARIABLE TRY_OUT - ARGS arg1 arg2) -if(NOT ARG_TEST_COMPILE) - message(SEND_ERROR "expect_arg failed compiling: ${TRY_OUT}") -endif() -if(NOT "${ARG_TEST_RUN}" STREQUAL "0") - message(SEND_ERROR "expect_arg failed running with exit code ${ARG_TEST_RUN} ${TRY_OUT}") -endif() - -# try to run a file that should compile and run, but return an error -try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/exit_with_error.c - COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT - RUN_OUTPUT_VARIABLE RUN_OUTPUT) - -if(NOT SHOULD_COMPILE) - message(STATUS " exit_with_error failed compiling: ${COMPILE_OUTPUT}") -endif() -if("${SHOULD_EXIT_WITH_ERROR}" STREQUAL "0") - message(SEND_ERROR " exit_with_error passed with exit code ${SHOULD_EXIT_WITH_ERROR}") -endif() - -# check the compile output, it should contain the filename -if(NOT "${COMPILE_OUTPUT}" MATCHES "exit_with_error") - message(SEND_ERROR " COMPILE_OUT didn't contain \"exit_with_error\": \"${COMPILE_OUTPUT}\"") -endif() -#... but not the run time output -if("${COMPILE_OUTPUT}" MATCHES "hello world") - message(SEND_ERROR " COMPILE_OUT contains the run output: \"${COMPILE_OUTPUT}\"") -endif() -# check the run output, it should stdout -if(NOT "${RUN_OUTPUT}" MATCHES "hello world") - message(SEND_ERROR " RUN_OUTPUT didn't contain \"hello world\": \"${RUN_OUTPUT}\"") -endif() - -####################################################################### -# -# also test that the CHECK_C_SOURCE_COMPILES, CHECK_CXX_SOURCE_COMPILES -# CHECK_C_SOURCE_RUNS and CHECK_CXX_SOURCE_RUNS macros work - -include(CheckCSourceCompiles) -include(CheckCXXSourceCompiles) -include(CheckCSourceRuns) -include(CheckCXXSourceRuns) - -CHECK_C_SOURCE_COMPILES("I don't build" C_BUILD_SHOULD_FAIL) -CHECK_C_SOURCE_COMPILES("int main() {return 0;}" C_BUILD_SHOULD_WORK) -CHECK_C_SOURCE_RUNS("int main() {return 1;}" C_RUN_SHOULD_FAIL) -CHECK_C_SOURCE_RUNS("int main() {return 0;}" C_RUN_SHOULD_WORK) - -TEST_FAIL(C_BUILD_SHOULD_FAIL "CHECK_C_SOURCE_COMPILES() succeeded, but should have failed") -TEST_ASSERT(C_BUILD_SHOULD_WORK "CHECK_C_SOURCE_COMPILES() failed") -TEST_FAIL(C_RUN_SHOULD_FAIL "CHECK_C_SOURCE_RUNS() succeeded, but should have failed") -TEST_ASSERT(C_RUN_SHOULD_WORK "CHECK_C_SOURCE_RUNS() failed") - -CHECK_CXX_SOURCE_COMPILES("I don't build" CXX_BUILD_SHOULD_FAIL) -CHECK_CXX_SOURCE_COMPILES("int main() {return 0;}" CXX_BUILD_SHOULD_WORK) -CHECK_CXX_SOURCE_COMPILES("void l(char const (&x)[2]){}; int main() { l(\"\\\\n\"); return 0;}" - CXX_BUILD_SHOULD_WORK_COMPLEX) - -CHECK_CXX_SOURCE_RUNS("int main() {return 2;}" CXX_RUN_SHOULD_FAIL) -CHECK_CXX_SOURCE_RUNS("int main() {return 0;}" CXX_RUN_SHOULD_WORK) - -TEST_FAIL(CXX_BUILD_SHOULD_FAIL "CHECK_CXX_SOURCE_COMPILES() succeeded, but should have failed") -TEST_ASSERT(CXX_BUILD_SHOULD_WORK "CHECK_CXX_SOURCE_COMPILES() failed") -TEST_ASSERT(CXX_BUILD_SHOULD_WORK_COMPLEX "CHECK_CXX_SOURCE_COMPILES() failed") -TEST_FAIL(CXX_RUN_SHOULD_FAIL "CHECK_CXX_SOURCE_RUNS() succeeded, but should have failed") -TEST_ASSERT(CXX_RUN_SHOULD_WORK "CHECK_CXX_SOURCE_RUNS() failed") - -foreach(lang C CXX) - if(NOT CMAKE_${lang}_COMPILER_ID STREQUAL "PathScale") - set(${lang}_DD --) - endif() -endforeach() - -unset(C_BOGUS_FLAG CACHE) -include(CheckCCompilerFlag) -CHECK_C_COMPILER_FLAG(${C_DD}-_this_is_not_a_flag_ C_BOGUS_FLAG) -TEST_FAIL(C_BOGUS_FLAG "CHECK_C_COMPILER_FLAG() succeeded, but should have failed") -unset(C_BOGUS_FLAG CACHE) -if(DEFINED C_BOGUS_FLAG) - # Verify that CHECK_C_COMPILER_FLAG didn't construct a normal variable - message(SEND_ERROR "CHECK_C_COMPILER_FLAG shouldn't construct C_BOGUS_FLAG as a normal variable") -endif() - -unset(CXX_BOGUS_FLAG CACHE) -include(CheckCXXCompilerFlag) -CHECK_CXX_COMPILER_FLAG(${CXX_DD}-_this_is_not_a_flag_ CXX_BOGUS_FLAG) -TEST_FAIL(CXX_BOGUS_FLAG "CHECK_CXX_COMPILER_FLAG() succeeded, but should have failed") -unset(CXX_BOGUS_FLAG CACHE) -if(DEFINED CXX_BOGUS_FLAG) - # Verify that CHECK_C_COMPILER_FLAG didn't construct a normal variable - message(SEND_ERROR "CHECK_CXX_COMPILER_FLAG shouldn't construct CXX_BOGUS_FLAG as a normal variable") -endif() - -if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "LCC") - unset(C_STRICT_PROTOTYPES CACHE) - CHECK_C_COMPILER_FLAG("-Werror;-Wstrict-prototypes" C_STRICT_PROTOTYPES) - TEST_ASSERT(C_STRICT_PROTOTYPES "CHECK_C_COMPILER_FLAG failed -Werror -Wstrict-prototypes") -endif() - -######################################################################### -# -# Test that the CHECK_OBJCC_SOURCE_COMPILES, CHECK_OBJCXX_SOURCE_COMPILES -# CHECK_OBJC_SOURCE_RUNS and CHECK_OBJCXX_SOURCE_RUNS macros work - -if (APPLE) - enable_language(OBJC) - enable_language(OBJCXX) - - include(CheckOBJCSourceCompiles) - include(CheckOBJCXXSourceCompiles) - include(CheckOBJCSourceRuns) - include(CheckOBJCXXSourceRuns) - - CHECK_OBJC_SOURCE_COMPILES("I don't build in Objective-C" OBJC_BUILD_SHOULD_FAIL) - CHECK_OBJC_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJC_BUILD_SHOULD_WORK) - - TEST_FAIL(OBJC_BUILD_SHOULD_FAIL "CHECK_OBJC_SOURCE_COMPILES() succeeded, but should have failed") - TEST_ASSERT(SIMPLE_OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded") - - set(CMAKE_REQUIRED_LIBRARIES "-framework Foundation") - - CHECK_OBJC_SOURCE_COMPILES("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_BUILD_SHOULD_WORK) - CHECK_OBJC_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJC_RUN_SHOULD_FAIL) - CHECK_OBJC_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJC_RUN_SHOULD_WORK) - CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 2;\n}\n" OBJC_RUN_SHOULD_FAIL) - CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_RUN_SHOULD_WORK) - - TEST_ASSERT(OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded") - TEST_FAIL(SIMPLE_OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURC_RUNS() succeeds, but should have failed") - TEST_ASSERT(SIMPLE_OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded") - TEST_FAIL(OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURCE_RUNS() succeeds, but should have failed") - TEST_ASSERT(OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded") - - - CHECK_OBJCXX_SOURCE_COMPILES("I don't build in Objective-C++" OBJCXX_BUILD_SHOULD_FAIL) - CHECK_OBJCXX_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJCXX_BUILD_SHOULD_WORK) - - TEST_FAIL(OBJCXX_BUILD_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_COMPILES() succeeded, but should have failed") - TEST_ASSERT(SIMPLE_OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded") - - CHECK_OBJCXX_SOURCE_COMPILES("#import <Foundation/Foundation.h>\n#include <iostream>\nint main()\n{\nNSObject *foo;\nstd::cout << \"Hello\" << std::endl;\nreturn 0;\n}\n" OBJCXX_BUILD_SHOULD_WORK) - CHECK_OBJCXX_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJCXX_RUN_SHOULD_FAIL) - CHECK_OBJCXX_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJCXX_RUN_SHOULD_WORK) - CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 2;\n}\n" OBJCXX_RUN_SHOULD_FAIL) - CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 0;\n}\n" OBJCXX_RUN_SHOULD_WORK) - - TEST_ASSERT(OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded") - TEST_FAIL(SIMPLE_OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURC_RUNS() succeeds, but should have failed") - TEST_ASSERT(SIMPLE_OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded") - TEST_FAIL(OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_RUNS() succeeds, but should have failed") - TEST_ASSERT(OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded") - - # try to compile a file that should compile - try_compile(SHOULD_PASS - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/pass.m - OUTPUT_VARIABLE TRY_OUT) - if(NOT SHOULD_PASS) - message(SEND_ERROR "should pass failed ${TRY_OUT}") - endif() - - # try to compile a file that should not compile - try_compile(SHOULD_FAIL - ${TryCompile_BINARY_DIR} - ${TryCompile_SOURCE_DIR}/fail.m - OUTPUT_VARIABLE TRY_OUT) - if(SHOULD_FAIL) - message(SEND_ERROR "Should fail passed ${TRY_OUT}") - endif() - -endif() - ####################################################################### # # also test that the check_prototype_definition macro works diff --git a/Tests/TryCompile/exit_with_error.c b/Tests/TryCompile/exit_with_error.c index f3c523d..dbddcf5 100644 --- a/Tests/TryCompile/exit_with_error.c +++ b/Tests/TryCompile/exit_with_error.c @@ -3,5 +3,5 @@ int main() { printf("hello world\n"); - return -1; + return 1; } diff --git a/Tests/TryCompile/old_and_new_signature_tests.cmake b/Tests/TryCompile/old_and_new_signature_tests.cmake new file mode 100644 index 0000000..ab548f7 --- /dev/null +++ b/Tests/TryCompile/old_and_new_signature_tests.cmake @@ -0,0 +1,276 @@ +# try to compile a file that should compile +try_compile(SHOULD_PASS + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/pass.c + OUTPUT_VARIABLE TRY_OUT) +EXPECT_PASS(SHOULD_PASS "${TRY_OUT}") + +# try to compile a file that should compile +# also check that COPY_FILE works +try_compile(SHOULD_PASS + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/pass.c + OUTPUT_VARIABLE TRY_OUT + COPY_FILE ${TryCompile_BINARY_DIR}/CopyOfPass + ) +EXPECT_PASS(SHOULD_PASS "${TRY_OUT}") + +if(NOT EXISTS "${TryCompile_BINARY_DIR}/CopyOfPass") + message(SEND_ERROR "COPY_FILE to \"${TryCompile_BINARY_DIR}/CopyOfPass\" failed") +else() + file(REMOVE "${TryCompile_BINARY_DIR}/CopyOfPass") +endif() + +# try to compile a file that should compile +# also check that COPY_FILE_ERROR works +file(WRITE ${TryCompile_BINARY_DIR}/invalid "") +try_compile(SHOULD_PASS + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/pass.c + OUTPUT_VARIABLE TRY_OUT + COPY_FILE ${TryCompile_BINARY_DIR}/invalid/path + COPY_FILE_ERROR _captured + ) +EXPECT_PASS(SHOULD_PASS "${TRY_OUT}") + +if(NOT _captured MATCHES "Cannot copy output executable.*/invalid/path") + message(SEND_ERROR "COPY_FILE_ERROR did not capture expected message") +endif() + +# try to compile a file that should not compile +try_compile(SHOULD_FAIL + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/fail.c + OUTPUT_VARIABLE TRY_OUT) +EXPECT_FAIL(SHOULD_FAIL "${TRY_OUT}") + +# try to compile two files that should compile +try_compile(SHOULD_PASS + ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} + ${TryCompile_SOURCE_DIR}/pass2a.c + ${TryCompile_SOURCE_DIR}/pass2b.cxx + OUTPUT_VARIABLE TRY_OUT) +EXPECT_PASS(SHOULD_PASS "${TRY_OUT}") + +# try to compile two files that should not compile +try_compile(SHOULD_FAIL + ${try_compile_bindir_or_SOURCES} + ${try_compile_redundant_SOURCES} + ${TryCompile_SOURCE_DIR}/fail2a.c + ${TryCompile_SOURCE_DIR}/fail2b.c + OUTPUT_VARIABLE TRY_OUT) +EXPECT_FAIL(SHOULD_FAIL "${TRY_OUT}") + +# try to compile a file that should compile +set(_c_flags "${CMAKE_C_FLAGS}") +if(WATCOM) + string(APPEND CMAKE_C_FLAGS " -dTESTDEF") +else() + string(APPEND CMAKE_C_FLAGS " \"-DTESTDEF\"") +endif() +try_compile(SHOULD_PASS + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/testdef.c + OUTPUT_VARIABLE TRY_OUT) +EXPECT_PASS(SHOULD_PASS "${TRY_OUT}") +set(CMAKE_C_FLAGS "${_c_flags}") + +try_compile(CMAKE_ANSI_FOR_SCOPE + ${try_compile_bindir_or_SOURCES} + ${CMAKE_ROOT}/Modules/TestForAnsiForScope.cxx OUTPUT_VARIABLE OUT) +if(CMAKE_ANSI_FOR_SCOPE) + message("Compiler supports ansi for") +else() + message("Compiler does not support ansi for scope") +endif() + +message("use the module now") +include(${CMAKE_ROOT}/Modules/TestForANSIForScope.cmake) +if(CMAKE_ANSI_FOR_SCOPE) + message("Compiler supports ansi for") +else() + message("Compiler does not support ansi for scope") +endif() + +# test that COMPILE_DEFINITIONS are correctly expanded +try_compile(COMPILE_DEFINITIONS_LIST_EXPANDED + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/check_a_b.c + OUTPUT_VARIABLE output + COMPILE_DEFINITIONS "-DDEF_A;-DDEF_B" + ) +if(COMPILE_DEFINITIONS_LIST_EXPANDED) + message(STATUS "COMPILE_DEFINITIONS list expanded correctly") +else() + string(REPLACE "\n" "\n " output " ${output}") + message(SEND_ERROR "COMPILE_DEFINITIONS list did not expand correctly\n${output}") +endif() + +# try to compile a file that doesn't exist +try_compile(SHOULD_FAIL_DUE_TO_BAD_SOURCE + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/pass.c + OUTPUT_VARIABLE output + COMPILE_DEFINITIONS "bad#source.c" + ) +if(SHOULD_FAIL_DUE_TO_BAD_SOURCE AND NOT CMAKE_GENERATOR MATCHES "Watcom WMake|NMake Makefiles") + string(REPLACE "\n" "\n " output " ${output}") + message(SEND_ERROR "try_compile with bad#source.c did not fail:\n${output}") +elseif(NOT output MATCHES [[(bad#source\.c|bad\.c|bad')]]) + string(REPLACE "\n" "\n " output " ${output}") + message(SEND_ERROR "try_compile with bad#source.c failed without mentioning bad source:\n${output}") +else() + message(STATUS "try_compile with bad#source.c correctly failed") +endif() + +if(APPLE) + # try to compile a file that should compile + try_compile(SHOULD_PASS + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/pass.m + OUTPUT_VARIABLE TRY_OUT) + EXPECT_PASS(SHOULD_PASS "${TRY_OUT}") + + # try to compile a file that should not compile + try_compile(SHOULD_FAIL + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/fail.m + OUTPUT_VARIABLE TRY_OUT) + EXPECT_FAIL(SHOULD_FAIL "${TRY_OUT}") +endif() + +# check that try_compile honors NO_CACHE +function(try_compile_scope_test) + try_compile( + CACHED_RESULT + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/pass.c) + try_compile( + SHOULD_NOT_ESCAPE_SCOPE_RESULT + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/pass.c + NO_CACHE) +endfunction() + +try_compile_scope_test() + +if(NOT DEFINED CACHE{CACHED_RESULT}) + message(SEND_ERROR " Result from try_compile was not cached") +endif() +if(DEFINED SHOULD_NOT_ESCAPE_SCOPE_RESULT) + message(SEND_ERROR " Result from try_compile(NO_CACHE) leaked") +endif() + +###################################### + +# now test try_run() + +# try to run a file that should compile and run without error +# also check that OUTPUT_VARIABLE contains both the compile output +# and the run output +try_run(SHOULD_RUN SHOULD_COMPILE + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/exit_success.c + ${try_compile_output_vars}) +EXPECT_COMPILED("exit_success" SHOULD_COMPILE "${${try_compile_compile_output_var}}") +EXPECT_RUN_RESULT("exit_success" SHOULD_RUN 0) + +# check the compile output for the filename +if(NOT "${${try_compile_compile_output_var}}" MATCHES "exit_success") + message(SEND_ERROR + " ${try_compile_compile_output_var} didn't contain \"exit_success\":" + " \"${${try_compile_compile_output_var}}\"") +endif() +# check the run output +if(NOT "${${try_compile_run_output_var}}" MATCHES "hello world") + message(SEND_ERROR + " ${try_compile_run_output_var} didn't contain \"hello world\":" + " \"${${try_compile_run_output_var}}\"") +endif() + +try_run(ARG_TEST_RUN ARG_TEST_COMPILE + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/expect_arg.c + COMPILE_OUTPUT_VARIABLE TRY_OUT + ARGS arg1 arg2) +EXPECT_COMPILED("expect_arg" ARG_TEST_COMPILE "${TRY_OUT}") +EXPECT_RUN_RESULT("expect_arg" ARG_TEST_RUN 0) + +# try to run a file that should compile and run, but return an error +try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/exit_with_error.c + COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT + RUN_OUTPUT_VARIABLE RUN_OUTPUT) +EXPECT_COMPILED("exit_with_error" SHOULD_COMPILE "${COMPILE_OUTPUT}") +EXPECT_RUN_RESULT("exit_with_error" SHOULD_EXIT_WITH_ERROR 1) + +# check the compile output, it should contain the filename +if(NOT "${COMPILE_OUTPUT}" MATCHES "exit_with_error") + message(SEND_ERROR " COMPILE_OUT didn't contain \"exit_with_error\": \"${COMPILE_OUTPUT}\"") +endif() +#... but not the run time output +if("${COMPILE_OUTPUT}" MATCHES "hello world") + message(SEND_ERROR " COMPILE_OUT contains the run output: \"${COMPILE_OUTPUT}\"") +endif() +# check the run output, it should contain stdout +if(NOT "${RUN_OUTPUT}" MATCHES "hello world") + message(SEND_ERROR " RUN_OUTPUT didn't contain \"hello world\": \"${RUN_OUTPUT}\"") +endif() + +# try to run a file and parse stdout and stderr separately +# also check that COPY_FILE works +try_run(SHOULD_EXIT_WITH_ERROR SHOULD_COMPILE + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/stdout_and_stderr.c + COPY_FILE ${TryCompile_BINARY_DIR}/CopyOfRun + COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT + RUN_OUTPUT_STDOUT_VARIABLE RUN_OUTPUT_STDOUT + RUN_OUTPUT_STDERR_VARIABLE RUN_OUTPUT_STDERR) +EXPECT_PASS(SHOULD_COMPILE "${COMPILE_OUTPUT}") + +if(NOT EXISTS "${TryCompile_BINARY_DIR}/CopyOfRun") + message(SEND_ERROR "COPY_FILE to \"${TryCompile_BINARY_DIR}/CopyOfRun\" failed") +else() + file(REMOVE "${TryCompile_BINARY_DIR}/CopyOfRun") +endif() + +# check the run stdout output +if(NOT "${RUN_OUTPUT_STDOUT}" MATCHES "hello world") + message(SEND_ERROR " RUN_OUTPUT_STDOUT didn't contain \"hello world\": \"${RUN_OUTPUT_STDOUT}\"") +endif() +# check the run stderr output +if(NOT "${RUN_OUTPUT_STDERR}" MATCHES "error") + message(SEND_ERROR " RUN_OUTPUT_STDERR didn't contain \"error\": \"${RUN_OUTPUT_STDERR}\"") +endif() + +# check that try_run honors NO_CACHE +function(try_run_scope_test) + try_run( + CACHED_RUN_RESULT + CACHED_COMPILE_RESULT + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/exit_success.c) + try_run( + SHOULD_NOT_ESCAPE_SCOPE_RUN_RESULT + SHOULD_NOT_ESCAPE_SCOPE_COMPILE_RESULT + ${try_compile_bindir_or_SOURCES} + ${TryCompile_SOURCE_DIR}/exit_success.c + NO_CACHE) +endfunction() + +try_run_scope_test() + +if(NOT DEFINED CACHE{CACHED_COMPILE_RESULT}) + message(SEND_ERROR " Compile result from try_run was not cached") +endif() +if(NOT DEFINED CACHE{CACHED_RUN_RESULT}) + message(SEND_ERROR " Run result from try_run was not cached") +endif() +if(DEFINED SHOULD_NOT_ESCAPE_SCOPE_COMPILE_RESULT) + message(SEND_ERROR " Compile result from try_run(NO_CACHE) leaked") +endif() +if(DEFINED SHOULD_NOT_ESCAPE_SCOPE_RUN_RESULT) + message(SEND_ERROR " Run result from try_run(NO_CACHE) leaked") +endif() diff --git a/Tests/TryCompile/stdout_and_stderr.c b/Tests/TryCompile/stdout_and_stderr.c new file mode 100644 index 0000000..84ded1f --- /dev/null +++ b/Tests/TryCompile/stdout_and_stderr.c @@ -0,0 +1,8 @@ +#include <stdio.h> + +int main() +{ + fputs("error\n", stderr); + puts("hello world\n"); + return 0; +} diff --git a/Tests/VSGNUFortran/CMakeLists.txt b/Tests/VSGNUFortran/CMakeLists.txt index 993d0d6..2b4f4fa 100644 --- a/Tests/VSGNUFortran/CMakeLists.txt +++ b/Tests/VSGNUFortran/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") # to be in the same directory. get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(_isMultiConfig) - foreach(config ${CMAKE_CONFIGURATION_TYPES}) + foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES) string(TOUPPER "${config}" config) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${config} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) diff --git a/Tests/VSWinStorePhone/VerifyAppPackage.cmake b/Tests/VSWinStorePhone/VerifyAppPackage.cmake index f9440d7..52e8a54 100644 --- a/Tests/VSWinStorePhone/VerifyAppPackage.cmake +++ b/Tests/VSWinStorePhone/VerifyAppPackage.cmake @@ -26,7 +26,7 @@ if(NOT result EQUAL 0) message(FATAL_ERROR "Listing app package content failed with: ${error}") endif() -foreach(app_pkg_item ${EXPECTED_APP_PKG_CONTENT}) +foreach(app_pkg_item IN LISTS EXPECTED_APP_PKG_CONTENT) string(FIND ${APP_PKG_CONTENT_OUTPUT} ${app_pkg_item} _found) if(_found EQUAL -1) message(FATAL_ERROR "Generated app package is missing an expected item: ${app_pkg_item}") diff --git a/Utilities/Doxygen/CMakeLists.txt b/Utilities/Doxygen/CMakeLists.txt index b712c27..bc16350 100644 --- a/Utilities/Doxygen/CMakeLists.txt +++ b/Utilities/Doxygen/CMakeLists.txt @@ -3,7 +3,7 @@ if(NOT CMake_SOURCE_DIR) set(CMakeDeveloperReference_STANDALONE 1) - cmake_minimum_required(VERSION 3.13...3.22 FATAL_ERROR) + cmake_minimum_required(VERSION 3.13...3.23 FATAL_ERROR) get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH) get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH) include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake) diff --git a/Utilities/IWYU/mapping.imp b/Utilities/IWYU/mapping.imp index b80fc22..b0ed911 100644 --- a/Utilities/IWYU/mapping.imp +++ b/Utilities/IWYU/mapping.imp @@ -91,7 +91,7 @@ { symbol: [ "std::__decay_and_strip<cmFindPackageCommand::PathLabel &>::__type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::__decay_and_strip<cmGlobalNinjaGenerator::TargetAlias &>::__type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::__decay_and_strip<__gnu_cxx::__normal_iterator<const cmCTestTestHandler::cmCTestTestProperties *, std::vector<cmCTestTestHandler::cmCTestTestProperties, std::allocator<cmCTestTestHandler::cmCTestTestProperties> > > &>::__type", private, "\"cmConfigure.h\"", public ] }, - { symbol: [ "std::__decay_and_strip<const __gnu_cxx::__normal_iterator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &, void *)> > *, std::vector<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &, void *)> >, std::allocator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &, void *)> > > > > &>::__type", private, "\"cmConfigure.h\"", public ] }, + { symbol: [ "std::__decay_and_strip<const __gnu_cxx::__normal_iterator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &)> > *, std::vector<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &)> >, std::allocator<std::pair<cm::string_view, std::function<void (ArgumentParser::Instance &)> > > > > &>::__type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::__success_type<std::chrono::duration<double, std::ratio<1, 1> > >::type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::__success_type<std::chrono::duration<long, std::ratio<1, 1000000000> > >::type", private, "\"cmConfigure.h\"", public ] }, { symbol: [ "std::enable_if<true, std::chrono::duration<long, std::ratio<1, 1> > >::type", private, "\"cmConfigure.h\"", public ] }, diff --git a/Utilities/Release/WiX/CustomAction/CMakeLists.txt b/Utilities/Release/WiX/CustomAction/CMakeLists.txt index 9d89dd8..dd07f9f 100644 --- a/Utilities/Release/WiX/CustomAction/CMakeLists.txt +++ b/Utilities/Release/WiX/CustomAction/CMakeLists.txt @@ -7,6 +7,10 @@ if(MSVC) "CMAKE_CXX_FLAGS_${CONFIG}" "${CMAKE_CXX_FLAGS_${CONFIG}}" ) + string(REPLACE "-MD" "-MT" + "CMAKE_CXX_FLAGS_${CONFIG}" + "${CMAKE_CXX_FLAGS_${CONFIG}}" + ) endforeach() endif() endif() diff --git a/Utilities/Release/linux/aarch64/Dockerfile b/Utilities/Release/linux/aarch64/Dockerfile index 9abae2a..e232c01 100644 --- a/Utilities/Release/linux/aarch64/Dockerfile +++ b/Utilities/Release/linux/aarch64/Dockerfile @@ -25,7 +25,7 @@ RUN : \ && nice make -j $(nproc) \ && if $TEST; then \ # Run tests that require the full build tree. - bin/ctest --output-on-failure -j 8 -R '^(CMake\.|CMakeLib\.|CMakeServerLib\.|RunCMake\.ctest_memcheck)'; \ + bin/ctest --output-on-failure -j 8 -R '^(CMake\.|CMakeLib\.|RunCMake\.ctest_memcheck)'; \ fi \ && bin/cpack -G TGZ \ && bin/cpack -G STGZ \ diff --git a/Utilities/Release/linux/x86_64/Dockerfile b/Utilities/Release/linux/x86_64/Dockerfile index 8c98d3e..736ee26 100644 --- a/Utilities/Release/linux/x86_64/Dockerfile +++ b/Utilities/Release/linux/x86_64/Dockerfile @@ -26,7 +26,7 @@ RUN : \ && nice make -j $(nproc) \ && if $TEST; then \ # Run tests that require the full build tree. - bin/ctest --output-on-failure -j 8 -R '^(CMake\.|CMakeLib\.|CMakeServerLib\.|RunCMake\.ctest_memcheck)'; \ + bin/ctest --output-on-failure -j 8 -R '^(CMake\.|CMakeLib\.|RunCMake\.ctest_memcheck)'; \ fi \ && bin/cpack -G TGZ \ && bin/cpack -G STGZ \ diff --git a/Utilities/Scripts/update-libuv.bash b/Utilities/Scripts/update-libuv.bash index 6d423a7..280c684 100755 --- a/Utilities/Scripts/update-libuv.bash +++ b/Utilities/Scripts/update-libuv.bash @@ -8,7 +8,7 @@ readonly name="libuv" readonly ownership="libuv upstream <libuv@googlegroups.com>" readonly subtree="Utilities/cmlibuv" readonly repo="https://github.com/libuv/libuv.git" -readonly tag="v1.x" +readonly tag="v1.44.2" readonly shortlog=false readonly paths=" LICENSE diff --git a/Utilities/Sphinx/CMakeLists.txt b/Utilities/Sphinx/CMakeLists.txt index fbce1c8..886f4e0 100644 --- a/Utilities/Sphinx/CMakeLists.txt +++ b/Utilities/Sphinx/CMakeLists.txt @@ -3,7 +3,7 @@ if(NOT CMake_SOURCE_DIR) set(CMakeHelp_STANDALONE 1) - cmake_minimum_required(VERSION 3.13...3.22 FATAL_ERROR) + cmake_minimum_required(VERSION 3.13...3.23 FATAL_ERROR) get_filename_component(tmp "${CMAKE_CURRENT_SOURCE_DIR}" PATH) get_filename_component(CMake_SOURCE_DIR "${tmp}" PATH) include(${CMake_SOURCE_DIR}/Modules/CTestUseLaunchers.cmake) @@ -118,12 +118,12 @@ if(SPHINX_QTHELP) COMMAND ${CMAKE_COMMAND} "-DCSS_DIR=${CMAKE_CURRENT_BINARY_DIR}/qthelp/_static" -P "${CMAKE_CURRENT_SOURCE_DIR}/apply_qthelp_css_workaround.cmake" # Workaround sphinx configurability: - # https://bitbucket.org/birkenfeld/sphinx/issue/1448/make-qthelp-more-configurable + # https://github.com/sphinx-doc/sphinx/issues/1448 COMMAND ${CMAKE_COMMAND} "-DQTHELP_DIR=${CMAKE_CURRENT_BINARY_DIR}/qthelp/" -P "${CMAKE_CURRENT_SOURCE_DIR}/fixup_qthelp_names.cmake" # Create proper identifiers. Workaround for - # https://bitbucket.org/birkenfeld/sphinx/issue/1491/qthelp-should-generate-identifiers-for + # https://github.com/sphinx-doc/sphinx/issues/1491 COMMAND "${Python_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/create_identifiers.py" "${CMAKE_CURRENT_BINARY_DIR}/qthelp/" @@ -161,7 +161,7 @@ endif() set(doc_format_outputs "") set(doc_format_last "") -foreach(format ${doc_formats}) +foreach(format IN LISTS doc_formats) set(doc_format_output "doc_format_${format}") set(doc_format_log "build-${format}.log") if(CMake_SPHINX_CMAKE_ORG) @@ -219,13 +219,7 @@ endforeach() add_custom_target(documentation ALL DEPENDS ${doc_format_outputs}) if(CMake_SPHINX_DEPEND_ON_EXECUTABLES) - foreach(t - cmake - ccmake - cmake-gui - cpack - ctest - ) + foreach(t IN ITEMS cmake ccmake cmake-gui cpack ctest) if(TARGET ${t}) # Build documentation after main executables. add_dependencies(documentation ${t}) @@ -248,7 +242,7 @@ endif() if(SPHINX_MAN) file(GLOB man_rst RELATIVE ${CMake_SOURCE_DIR}/Help/manual ${CMake_SOURCE_DIR}/Help/manual/*.[1-9].rst) - foreach(m ${man_rst}) + foreach(m IN LISTS man_rst) if("x${m}" MATCHES "^x(.+)\\.([1-9])\\.rst$") set(name "${CMAKE_MATCH_1}") set(sec "${CMAKE_MATCH_2}") diff --git a/Utilities/Sphinx/cmake.py b/Utilities/Sphinx/cmake.py index 9215e14..c7b1233 100644 --- a/Utilities/Sphinx/cmake.py +++ b/Utilities/Sphinx/cmake.py @@ -59,12 +59,6 @@ CMakeLexer.tokens["root"] = [ from docutils.parsers.rst import Directive, directives from docutils.transforms import Transform -try: - from docutils.utils.error_reporting import SafeString, ErrorString -except ImportError: - # error_reporting was not in utils before version 0.11: - from docutils.error_reporting import SafeString, ErrorString - from docutils import io, nodes from sphinx.directives import ObjectDescription @@ -130,13 +124,13 @@ class CMakeModule(Directive): f = io.FileInput(source_path=path, encoding=encoding, error_handler=e_handler) except UnicodeEncodeError as error: - raise self.severe('Problems with "%s" directive path:\n' - 'Cannot encode input file path "%s" ' - '(wrong locale?).' % - (self.name, SafeString(path))) + msg = ('Problems with "%s" directive path:\n' + 'Cannot encode input file path "%s" ' + '(wrong locale?).' % (self.name, path)) + raise self.severe(msg) except IOError as error: - raise self.severe('Problems with "%s" directive path:\n%s.' % - (self.name, ErrorString(error))) + msg = 'Problems with "%s" directive path:\n%s.' % (self.name, error) + raise self.severe(msg) raw_lines = f.read().splitlines() f.close() rst = None diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt index f842270..9b468c3 100644 --- a/Utilities/cmcurl/CMakeLists.txt +++ b/Utilities/cmcurl/CMakeLists.txt @@ -852,11 +852,11 @@ endif() # Check for symbol dlopen (same as HAVE_LIBDL) check_library_exists("${CURL_LIBS}" dlopen "" HAVE_DLOPEN) -if(0) # This code not needed for building within CMake. set(HAVE_LIBZ OFF) set(HAVE_ZLIB_H OFF) set(USE_ZLIB OFF) -optional_dependency(ZLIB) +#optional_dependency(ZLIB) +find_package(ZLIB) if(ZLIB_FOUND) set(HAVE_ZLIB_H ON) set(HAVE_LIBZ ON) @@ -870,19 +870,8 @@ if(ZLIB_FOUND) else() list(APPEND CURL_LIBS ${ZLIB_LIBRARIES}) include_directories(${ZLIB_INCLUDE_DIRS}) + list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS}) endif() - list(APPEND CMAKE_REQUIRED_INCLUDES ${ZLIB_INCLUDE_DIRS}) -endif() -endif() - -#----------------------------------------------------------------------------- -# CMake-specific curl code. - -if(CURL_SPECIAL_LIBZ) - set(CURL_LIBS ${CURL_LIBS} "${CURL_SPECIAL_LIBZ}") - include_directories(${CURL_SPECIAL_LIBZ_INCLUDES}) - set(HAVE_LIBZ 0) - set(HAVE_ZLIB_H 0) endif() option(CURL_BROTLI "Set to ON to enable building curl with brotli support." OFF) @@ -1465,6 +1454,8 @@ if(MSVC) add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) if(CMAKE_C_FLAGS MATCHES "/W[0-4]") string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + elseif(CMAKE_C_FLAGS MATCHES "-W[0-4]") + string(REGEX REPLACE "-W[0-4]" "-W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") endif() diff --git a/Utilities/cmcurl/lib/content_encoding.c b/Utilities/cmcurl/lib/content_encoding.c index c03637a..4c723c3 100644 --- a/Utilities/cmcurl/lib/content_encoding.c +++ b/Utilities/cmcurl/lib/content_encoding.c @@ -27,7 +27,7 @@ #include <stddef.h> #ifdef HAVE_ZLIB_H -#include <zlib.h> +#include <cm3p/zlib.h> #endif #ifdef HAVE_BROTLI diff --git a/Utilities/cmcurl/lib/version.c b/Utilities/cmcurl/lib/version.c index e37253d..5e3e428 100644 --- a/Utilities/cmcurl/lib/version.c +++ b/Utilities/cmcurl/lib/version.c @@ -51,7 +51,7 @@ #endif #ifdef HAVE_ZLIB_H -#include <zlib.h> +#include <cm3p/zlib.h> #endif #ifdef HAVE_BROTLI diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c index 635e9c1..5d1203b 100644 --- a/Utilities/cmcurl/lib/vtls/openssl.c +++ b/Utilities/cmcurl/lib/vtls/openssl.c @@ -217,8 +217,10 @@ * BoringSSL: supported since 5fd1807d95f7 (committed 2016-09-30) * LibreSSL: since 2.5.3 (April 12, 2017) */ -#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) || \ - defined(OPENSSL_IS_BORINGSSL) +#if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) && \ + !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20503000L)) || \ + defined(OPENSSL_IS_BORINGSSL) #define HAVE_SSL_CTX_SET_EC_CURVES #endif @@ -2282,6 +2284,14 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, # define HAS_NPN 1 #endif +/* Check for OpenSSL 1.1.0 which has set_{min,max}_proto_version(). */ +#undef HAS_MODERN_SET_PROTO_VER +#if OPENSSL_VERSION_NUMBER >= 0x10100000L \ + && !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20600000L) +# define HAS_MODERN_SET_PROTO_VER 1 +#endif + #ifdef HAS_NPN /* @@ -2340,7 +2350,7 @@ select_next_proto_cb(SSL *ssl, } #endif /* HAS_NPN */ -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */ +#ifdef HAS_MODERN_SET_PROTO_VER static CURLcode set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) { @@ -2424,7 +2434,7 @@ set_ssl_version_min_max(SSL_CTX *ctx, struct connectdata *conn) return CURLE_OK; } -#endif +#endif /* HAS_MODERN_SET_PROTO_VER */ #ifdef OPENSSL_IS_BORINGSSL typedef uint32_t ctx_option_t; @@ -2434,7 +2444,7 @@ typedef uint64_t ctx_option_t; typedef long ctx_option_t; #endif -#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */ +#if !defined(HAS_MODERN_SET_PROTO_VER) static CURLcode set_ssl_version_min_max_legacy(ctx_option_t *ctx_options, struct Curl_easy *data, @@ -2509,7 +2519,7 @@ set_ssl_version_min_max_legacy(ctx_option_t *ctx_options, } return CURLE_OK; } -#endif +#endif /* ! HAS_MODERN_SET_PROTO_VER */ /* The "new session" callback must return zero if the session can be removed * or non-zero if the session has been put into the session cache. @@ -2813,7 +2823,7 @@ static CURLcode ossl_connect_step1(struct Curl_easy *data, ctx_options |= SSL_OP_NO_SSLv2; ctx_options |= SSL_OP_NO_SSLv3; -#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */ +#if HAS_MODERN_SET_PROTO_VER /* 1.1.0 */ result = set_ssl_version_min_max(backend->ctx, conn); #else result = set_ssl_version_min_max_legacy(&ctx_options, data, conn, diff --git a/Utilities/cmjsoncpp/CMakeLists.txt b/Utilities/cmjsoncpp/CMakeLists.txt index c384f4e..09579d2 100644 --- a/Utilities/cmjsoncpp/CMakeLists.txt +++ b/Utilities/cmjsoncpp/CMakeLists.txt @@ -21,5 +21,5 @@ include_directories( ) add_library(cmjsoncpp ${JSONCPP_SOURCES}) -target_link_libraries(cmjsoncpp ${CMake_KWIML_LIBRARIES}) +target_link_libraries(cmjsoncpp $<TARGET_NAME_IF_EXISTS:kwiml::kwiml>) set_property(TARGET cmjsoncpp PROPERTY CXX_INCLUDE_WHAT_YOU_USE "") diff --git a/Utilities/cmlibarchive/CMakeLists.txt b/Utilities/cmlibarchive/CMakeLists.txt index eea472f..b38e653 100644 --- a/Utilities/cmlibarchive/CMakeLists.txt +++ b/Utilities/cmlibarchive/CMakeLists.txt @@ -442,6 +442,8 @@ SET(ADDITIONAL_LIBS "") # IF(ENABLE_ZLIB) FIND_PACKAGE(ZLIB) + SET(ZLIB_INCLUDE_DIR "") + SET(ZLIB_LIBRARIES ZLIB::ZLIB) ELSE() SET(ZLIB_FOUND FALSE) # Override cached value ENDIF() diff --git a/Utilities/cmlibuv/CMakeLists.txt b/Utilities/cmlibuv/CMakeLists.txt index b815a5c..ad3d433 100644 --- a/Utilities/cmlibuv/CMakeLists.txt +++ b/Utilities/cmlibuv/CMakeLists.txt @@ -27,6 +27,8 @@ set(uv_sources src/queue.h src/strscpy.c src/strscpy.h + src/strtok.c + src/strtok.h src/threadpool.c src/timer.c src/uv-common.c diff --git a/Utilities/cmlibuv/include/uv.h b/Utilities/cmlibuv/include/uv.h index 747095f..ffe34ec 100644 --- a/Utilities/cmlibuv/include/uv.h +++ b/Utilities/cmlibuv/include/uv.h @@ -1150,8 +1150,8 @@ struct uv_interface_address_s { struct uv_passwd_s { char* username; - long uid; - long gid; + unsigned long uid; + unsigned long gid; char* shell; char* homedir; }; @@ -1259,6 +1259,7 @@ UV_EXTERN uv_pid_t uv_os_getppid(void); UV_EXTERN int uv_os_getpriority(uv_pid_t pid, int* priority); UV_EXTERN int uv_os_setpriority(uv_pid_t pid, int priority); +UV_EXTERN unsigned int uv_available_parallelism(void); UV_EXTERN int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count); UV_EXTERN void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count); UV_EXTERN int uv_cpumask_size(void); diff --git a/Utilities/cmlibuv/include/uv/version.h b/Utilities/cmlibuv/include/uv/version.h index 1934f39..9c9d292 100644 --- a/Utilities/cmlibuv/include/uv/version.h +++ b/Utilities/cmlibuv/include/uv/version.h @@ -31,10 +31,10 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 43 -#define UV_VERSION_PATCH 1 -#define UV_VERSION_IS_RELEASE 0 -#define UV_VERSION_SUFFIX "dev" +#define UV_VERSION_MINOR 44 +#define UV_VERSION_PATCH 2 +#define UV_VERSION_IS_RELEASE 1 +#define UV_VERSION_SUFFIX "" #define UV_VERSION_HEX ((UV_VERSION_MAJOR << 16) | \ (UV_VERSION_MINOR << 8) | \ diff --git a/Utilities/cmlibuv/include/uv/win.h b/Utilities/cmlibuv/include/uv/win.h index e3fe37d..2662b0a 100644 --- a/Utilities/cmlibuv/include/uv/win.h +++ b/Utilities/cmlibuv/include/uv/win.h @@ -234,7 +234,7 @@ typedef struct _AFD_POLL_INFO { AFD_POLL_HANDLE_INFO Handles[1]; } AFD_POLL_INFO, *PAFD_POLL_INFO; -#define UV_MSAFD_PROVIDER_COUNT 3 +#define UV_MSAFD_PROVIDER_COUNT 4 /** @@ -388,6 +388,12 @@ typedef struct { OVERLAPPED overlapped; \ size_t queued_bytes; \ } io; \ + /* in v2, we can move these to the UV_CONNECT_PRIVATE_FIELDS */ \ + struct { \ + ULONG_PTR result; /* overlapped.Internal is reused to hold the result */\ + HANDLE pipeHandle; \ + DWORD duplex_flags; \ + } connect; \ } u; \ struct uv_req_s* next_req; diff --git a/Utilities/cmlibuv/src/fs-poll.c b/Utilities/cmlibuv/src/fs-poll.c index 89864e2..1bac1c5 100644 --- a/Utilities/cmlibuv/src/fs-poll.c +++ b/Utilities/cmlibuv/src/fs-poll.c @@ -25,7 +25,7 @@ #ifdef _WIN32 #include "win/internal.h" #include "win/handle-inl.h" -#define uv__make_close_pending(h) uv_want_endgame((h)->loop, (h)) +#define uv__make_close_pending(h) uv__want_endgame((h)->loop, (h)) #else #include "unix/internal.h" #endif diff --git a/Utilities/cmlibuv/src/idna.c b/Utilities/cmlibuv/src/idna.c index b44cb16..93d982c 100644 --- a/Utilities/cmlibuv/src/idna.c +++ b/Utilities/cmlibuv/src/idna.c @@ -21,6 +21,7 @@ #include "idna.h" #include <assert.h> #include <string.h> +#include <limits.h> /* UINT_MAX */ static unsigned uv__utf8_decode1_slow(const char** p, const char* pe, @@ -129,7 +130,7 @@ static int uv__idna_toascii_label(const char* s, const char* se, while (s < se) { c = uv__utf8_decode1(&s, se); - if (c == -1u) + if (c == UINT_MAX) return UV_EINVAL; if (c < 128) @@ -151,7 +152,7 @@ static int uv__idna_toascii_label(const char* s, const char* se, s = ss; while (s < se) { c = uv__utf8_decode1(&s, se); - assert(c != -1u); + assert(c != UINT_MAX); if (c > 127) continue; @@ -182,7 +183,7 @@ static int uv__idna_toascii_label(const char* s, const char* se, while (s < se) { c = uv__utf8_decode1(&s, se); - assert(c != -1u); + assert(c != UINT_MAX); if (c >= n) if (c < m) @@ -201,7 +202,7 @@ static int uv__idna_toascii_label(const char* s, const char* se, s = ss; while (s < se) { c = uv__utf8_decode1(&s, se); - assert(c != -1u); + assert(c != UINT_MAX); if (c < n) if (++delta == 0) @@ -280,7 +281,7 @@ long uv__idna_toascii(const char* s, const char* se, char* d, char* de) { st = si; c = uv__utf8_decode1(&si, se); - if (c == -1u) + if (c == UINT_MAX) return UV_EINVAL; if (c != '.') diff --git a/Utilities/cmlibuv/src/strscpy.h b/Utilities/cmlibuv/src/strscpy.h index cc78149..e8d4724 100644 --- a/Utilities/cmlibuv/src/strscpy.h +++ b/Utilities/cmlibuv/src/strscpy.h @@ -28,7 +28,7 @@ */ #include "uv.h" -/* Copies up to |n-1| bytes from |d| to |s| and always zero-terminates +/* Copies up to |n-1| bytes from |s| to |d| and always zero-terminates * the result, except when |n==0|. Returns the number of bytes copied * or UV_E2BIG if |d| is too small. * diff --git a/Utilities/cmlibuv/src/strtok.c b/Utilities/cmlibuv/src/strtok.c new file mode 100644 index 0000000..45ddea5 --- /dev/null +++ b/Utilities/cmlibuv/src/strtok.c @@ -0,0 +1,52 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <stdlib.h> +#include "strtok.h" + +char* uv__strtok(char* str, const char* sep, char** itr) { + const char* sep_itr; + char* tmp; + char* start; + + if (str == NULL) + start = tmp = *itr; + else + start = tmp = str; + + if (tmp == NULL) + return NULL; + + while (*tmp != '\0') { + sep_itr = sep; + while (*sep_itr != '\0') { + if (*tmp == *sep_itr) { + *itr = tmp + 1; + *tmp = '\0'; + return start; + } + sep_itr++; + } + tmp++; + } + *itr = NULL; + return start; +} diff --git a/Utilities/cmlibuv/src/strtok.h b/Utilities/cmlibuv/src/strtok.h new file mode 100644 index 0000000..3799ff5 --- /dev/null +++ b/Utilities/cmlibuv/src/strtok.h @@ -0,0 +1,27 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_STRTOK_H_ +#define UV_STRTOK_H_ + +char* uv__strtok(char* str, const char* sep, char** itr); + +#endif /* UV_STRTOK_H_ */ diff --git a/Utilities/cmlibuv/src/unix/atomic-ops.h b/Utilities/cmlibuv/src/unix/atomic-ops.h index 63d8268..2b58162 100644 --- a/Utilities/cmlibuv/src/unix/atomic-ops.h +++ b/Utilities/cmlibuv/src/unix/atomic-ops.h @@ -43,12 +43,11 @@ UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { __compare_and_swap((volatile int*)ptr, &oldval, newval); return oldval; #elif defined(__MVS__) - unsigned int op4; - if (__plo_CSST(ptr, (unsigned int*) &oldval, newval, - (unsigned int*) ptr, *ptr, &op4)) - return oldval; - else - return op4; + /* Use hand-rolled assembly because codegen from builtin __plo_CSST results in + * a runtime bug. + */ + __asm(" cs %0,%2,%1 \n " : "+r"(oldval), "+m"(*ptr) : "r"(newval) :); + return oldval; #elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) return atomic_cas_uint((uint_t *)ptr, (uint_t)oldval, (uint_t)newval); #else @@ -61,7 +60,9 @@ UV_UNUSED(static void cpu_relax(void)) { __asm__ __volatile__ ("rep; nop" ::: "memory"); /* a.k.a. PAUSE */ #elif (defined(__arm__) && __ARM_ARCH >= 7) || defined(__aarch64__) __asm__ __volatile__ ("yield" ::: "memory"); -#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) +#elif (defined(__ppc__) || defined(__ppc64__)) && defined(__APPLE__) + __asm volatile ("" : : : "memory"); +#elif !defined(__APPLE__) && (defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__)) __asm__ __volatile__ ("or 1,1,1; or 2,2,2" ::: "memory"); #endif } diff --git a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c index e48934b..11ca955 100644 --- a/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c +++ b/Utilities/cmlibuv/src/unix/bsd-ifaddrs.c @@ -27,7 +27,7 @@ #include <ifaddrs.h> #include <net/if.h> -#if !defined(__CYGWIN__) && !defined(__MSYS__) +#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__) #include <net/if_dl.h> #endif @@ -40,7 +40,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { return 1; if (ent->ifa_addr == NULL) return 1; -#if !defined(__CYGWIN__) && !defined(__MSYS__) +#if !defined(__CYGWIN__) && !defined(__MSYS__) && !defined(__GNU__) /* * If `exclude_type` is `UV__EXCLUDE_IFPHYS`, return whether `sa_family` * equals `AF_LINK`. Otherwise, the result depends on the operating @@ -69,7 +69,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { struct ifaddrs* addrs; struct ifaddrs* ent; uv_interface_address_t* address; -#if !(defined(__CYGWIN__) || defined(__MSYS__)) +#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__) int i; #endif @@ -126,7 +126,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address++; } -#if !(defined(__CYGWIN__) || defined(__MSYS__)) +#if !(defined(__CYGWIN__) || defined(__MSYS__)) && !defined(__GNU__) /* Fill in physical addresses for each interface */ for (ent = addrs; ent != NULL; ent = ent->ifa_next) { if (uv__ifaddr_exclude(ent, UV__EXCLUDE_IFPHYS)) diff --git a/Utilities/cmlibuv/src/unix/bsd-proctitle.c b/Utilities/cmlibuv/src/unix/bsd-proctitle.c index 4f4e9e5..b0c01e2 100644 --- a/Utilities/cmlibuv/src/unix/bsd-proctitle.c +++ b/Utilities/cmlibuv/src/unix/bsd-proctitle.c @@ -38,6 +38,7 @@ static void init_process_title_mutex_once(void) { void uv__process_title_cleanup(void) { + uv_once(&process_title_mutex_once, init_process_title_mutex_once); uv_mutex_destroy(&process_title_mutex); } diff --git a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c index 0f279d5..394231d 100644 --- a/Utilities/cmlibuv/src/unix/cmake-bootstrap.c +++ b/Utilities/cmlibuv/src/unix/cmake-bootstrap.c @@ -135,7 +135,9 @@ int uv__statx(int dirfd, errno = ENOSYS; return -1; } +#endif +#if defined(__linux__) || defined(__FreeBSD__) ssize_t uv__fs_copy_file_range(int fd_in, off_t* off_in, int fd_out, off_t* off_out, size_t len, unsigned int flags) diff --git a/Utilities/cmlibuv/src/unix/core.c b/Utilities/cmlibuv/src/unix/core.c index 0793922..d0b0e00 100644 --- a/Utilities/cmlibuv/src/unix/core.c +++ b/Utilities/cmlibuv/src/unix/core.c @@ -20,6 +20,7 @@ #include "uv.h" #include "internal.h" +#include "strtok.h" #include <stddef.h> /* NULL */ #include <stdio.h> /* printf */ @@ -86,10 +87,12 @@ extern char** environ; #endif #if defined(__MVS__) -#include <sys/ioctl.h> +# include <sys/ioctl.h> +# include "zos-sys-info.h" #endif #if defined(__linux__) +# include <sched.h> # include <sys/syscall.h> # define uv__accept4 accept4 #endif @@ -98,7 +101,7 @@ extern char** environ; # include <sanitizer/linux_syscall_hooks.h> #endif -static int uv__run_pending(uv_loop_t* loop); +static void uv__run_pending(uv_loop_t* loop); /* Verify that uv_buf_t is ABI-compatible with struct iovec. */ STATIC_ASSERT(sizeof(uv_buf_t) == sizeof(struct iovec)); @@ -164,6 +167,15 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { case UV_FS_EVENT: uv__fs_event_close((uv_fs_event_t*)handle); +#if defined(__sun) || defined(__MVS__) + /* + * On Solaris, illumos, and z/OS we will not be able to dissociate the + * watcher for an event which is pending delivery, so we cannot always call + * uv__make_close_pending() straight away. The backend will call the + * function once the event has cleared. + */ + return; +#endif break; case UV_POLL: @@ -340,42 +352,43 @@ int uv_backend_fd(const uv_loop_t* loop) { } -int uv_backend_timeout(const uv_loop_t* loop) { - if (loop->stop_flag != 0) - return 0; - - if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop)) - return 0; - - if (!QUEUE_EMPTY(&loop->idle_handles)) - return 0; - - if (!QUEUE_EMPTY(&loop->pending_queue)) - return 0; +static int uv__loop_alive(const uv_loop_t* loop) { + return uv__has_active_handles(loop) || + uv__has_active_reqs(loop) || + !QUEUE_EMPTY(&loop->pending_queue) || + loop->closing_handles != NULL; +} - if (loop->closing_handles) - return 0; - return uv__next_timeout(loop); +static int uv__backend_timeout(const uv_loop_t* loop) { + if (loop->stop_flag == 0 && + /* uv__loop_alive(loop) && */ + (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) && + QUEUE_EMPTY(&loop->pending_queue) && + QUEUE_EMPTY(&loop->idle_handles) && + loop->closing_handles == NULL) + return uv__next_timeout(loop); + return 0; } -static int uv__loop_alive(const uv_loop_t* loop) { - return uv__has_active_handles(loop) || - uv__has_active_reqs(loop) || - loop->closing_handles != NULL; +int uv_backend_timeout(const uv_loop_t* loop) { + if (QUEUE_EMPTY(&loop->watcher_queue)) + return uv__backend_timeout(loop); + /* Need to call uv_run to update the backend fd state. */ + return 0; } int uv_loop_alive(const uv_loop_t* loop) { - return uv__loop_alive(loop); + return uv__loop_alive(loop); } int uv_run(uv_loop_t* loop, uv_run_mode mode) { int timeout; int r; - int ran_pending; + int can_sleep; r = uv__loop_alive(loop); if (!r) @@ -384,16 +397,25 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { while (r != 0 && loop->stop_flag == 0) { uv__update_time(loop); uv__run_timers(loop); - ran_pending = uv__run_pending(loop); + + can_sleep = + QUEUE_EMPTY(&loop->pending_queue) && QUEUE_EMPTY(&loop->idle_handles); + + uv__run_pending(loop); uv__run_idle(loop); uv__run_prepare(loop); timeout = 0; - if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) - timeout = uv_backend_timeout(loop); + if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT) + timeout = uv__backend_timeout(loop); uv__io_poll(loop, timeout); + /* Process immediate callbacks (e.g. write_cb) a small fixed number of + * times to avoid loop starvation.*/ + for (r = 0; r < 8 && !QUEUE_EMPTY(&loop->pending_queue); r++) + uv__run_pending(loop); + /* Run one final update on the provider_idle_time in case uv__io_poll * returned because the timeout expired, but no events were received. This * call will be ignored if the provider_entry_time was either never set (if @@ -603,20 +625,6 @@ int uv__nonblock_ioctl(int fd, int set) { return 0; } - - -int uv__cloexec_ioctl(int fd, int set) { - int r; - - do - r = ioctl(fd, set ? FIOCLEX : FIONCLEX); - while (r == -1 && errno == EINTR); - - if (r) - return UV__ERR(errno); - - return 0; -} #endif @@ -651,25 +659,13 @@ int uv__nonblock_fcntl(int fd, int set) { } -int uv__cloexec_fcntl(int fd, int set) { +int uv__cloexec(int fd, int set) { int flags; int r; - do - r = fcntl(fd, F_GETFD); - while (r == -1 && errno == EINTR); - - if (r == -1) - return UV__ERR(errno); - - /* Bail out now if already set/clear. */ - if (!!(r & FD_CLOEXEC) == !!set) - return 0; - + flags = 0; if (set) - flags = r | FD_CLOEXEC; - else - flags = r & ~FD_CLOEXEC; + flags = FD_CLOEXEC; do r = fcntl(fd, F_SETFD, flags); @@ -683,28 +679,23 @@ int uv__cloexec_fcntl(int fd, int set) { ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { - struct cmsghdr* cmsg; +#if defined(__ANDROID__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) || \ + defined(__linux__) ssize_t rc; + rc = recvmsg(fd, msg, flags | MSG_CMSG_CLOEXEC); + if (rc == -1) + return UV__ERR(errno); + return rc; +#else + struct cmsghdr* cmsg; int* pfd; int* end; -#if defined(__linux__) - static int no_msg_cmsg_cloexec; - if (0 == uv__load_relaxed(&no_msg_cmsg_cloexec)) { - rc = recvmsg(fd, msg, flags | 0x40000000); /* MSG_CMSG_CLOEXEC */ - if (rc != -1) - return rc; - if (errno != EINVAL) - return UV__ERR(errno); - rc = recvmsg(fd, msg, flags); - if (rc == -1) - return UV__ERR(errno); - uv__store_relaxed(&no_msg_cmsg_cloexec, 1); - } else { - rc = recvmsg(fd, msg, flags); - } -#else + ssize_t rc; rc = recvmsg(fd, msg, flags); -#endif if (rc == -1) return UV__ERR(errno); if (msg->msg_controllen == 0) @@ -717,6 +708,7 @@ ssize_t uv__recvmsg(int fd, struct msghdr* msg, int flags) { pfd += 1) uv__cloexec(*pfd, 1); return rc; +#endif } @@ -809,14 +801,11 @@ int uv_fileno(const uv_handle_t* handle, uv_os_fd_t* fd) { } -static int uv__run_pending(uv_loop_t* loop) { +static void uv__run_pending(uv_loop_t* loop) { QUEUE* q; QUEUE pq; uv__io_t* w; - if (QUEUE_EMPTY(&loop->pending_queue)) - return 0; - QUEUE_MOVE(&loop->pending_queue, &pq); while (!QUEUE_EMPTY(&pq)) { @@ -826,8 +815,6 @@ static int uv__run_pending(uv_loop_t* loop) { w = QUEUE_DATA(q, uv__io_t, pending_queue); w->cb(loop, w, POLLOUT); } - - return 1; } @@ -1042,6 +1029,32 @@ int uv__open_cloexec(const char* path, int flags) { } +int uv__slurp(const char* filename, char* buf, size_t len) { + ssize_t n; + int fd; + + assert(len > 0); + + fd = uv__open_cloexec(filename, O_RDONLY); + if (fd < 0) + return fd; + + do + n = read(fd, buf, len - 1); + while (n == -1 && errno == EINTR); + + if (uv__close_nocheckstdio(fd)) + abort(); + + if (n < 0) + return UV__ERR(errno); + + buf[n] = '\0'; + + return 0; +} + + int uv__dup2_cloexec(int oldfd, int newfd) { #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__linux__) int r; @@ -1166,24 +1179,17 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { size_t name_size; size_t homedir_size; size_t shell_size; - long initsize; int r; if (pwd == NULL) return UV_EINVAL; - initsize = sysconf(_SC_GETPW_R_SIZE_MAX); - - if (initsize <= 0) - bufsize = 4096; - else - bufsize = (size_t) initsize; - uid = geteuid(); - buf = NULL; - for (;;) { - uv__free(buf); + /* Calling sysconf(_SC_GETPW_R_SIZE_MAX) would get the suggested size, but it + * is frequently 1024 or 4096, so we can just use that directly. The pwent + * will not usually be large. */ + for (bufsize = 2000;; bufsize *= 2) { buf = uv__malloc(bufsize); if (buf == NULL) @@ -1193,21 +1199,18 @@ int uv__getpwuid_r(uv_passwd_t* pwd) { r = getpwuid_r(uid, &pw, buf, bufsize, &result); while (r == EINTR); + if (r != 0 || result == NULL) + uv__free(buf); + if (r != ERANGE) break; - - bufsize *= 2; } - if (r != 0) { - uv__free(buf); + if (r != 0) return UV__ERR(r); - } - if (result == NULL) { - uv__free(buf); + if (result == NULL) return UV_ENOENT; - } /* Allocate memory for the username, shell, and home directory */ name_size = strlen(pw.pw_name) + 1; @@ -1569,6 +1572,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) { char* cloned_path; char* path_env; char* token; + char* itr; if (buf == NULL || buflen == NULL || *buflen == 0) return UV_EINVAL; @@ -1610,7 +1614,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) { if (cloned_path == NULL) return UV_ENOMEM; - token = strtok(cloned_path, ":"); + token = uv__strtok(cloned_path, ":", &itr); while (token != NULL) { snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, prog); if (realpath(trypath, abspath) == abspath) { @@ -1629,10 +1633,50 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) { return 0; } } - token = strtok(NULL, ":"); + token = uv__strtok(NULL, ":", &itr); } uv__free(cloned_path); /* Out of tokens (path entries), and no match found */ return UV_EINVAL; } + + +unsigned int uv_available_parallelism(void) { +#ifdef __linux__ + cpu_set_t set; + long rc; + + memset(&set, 0, sizeof(set)); + + /* sysconf(_SC_NPROCESSORS_ONLN) in musl calls sched_getaffinity() but in + * glibc it's... complicated... so for consistency try sched_getaffinity() + * before falling back to sysconf(_SC_NPROCESSORS_ONLN). + */ + if (0 == sched_getaffinity(0, sizeof(set), &set)) + rc = CPU_COUNT(&set); + else + rc = sysconf(_SC_NPROCESSORS_ONLN); + + if (rc < 1) + rc = 1; + + return (unsigned) rc; +#elif defined(__MVS__) + int rc; + + rc = __get_num_online_cpus(); + if (rc < 1) + rc = 1; + + return (unsigned) rc; +#else /* __linux__ */ + long rc; + + rc = sysconf(_SC_NPROCESSORS_ONLN); + if (rc < 1) + rc = 1; + + return (unsigned) rc; +#endif /* __linux__ */ +} diff --git a/Utilities/cmlibuv/src/unix/freebsd.c b/Utilities/cmlibuv/src/unix/freebsd.c index 170b897..658ff26 100644 --- a/Utilities/cmlibuv/src/unix/freebsd.c +++ b/Utilities/cmlibuv/src/unix/freebsd.c @@ -287,3 +287,18 @@ int uv__recvmmsg(int fd, struct uv__mmsghdr* mmsg, unsigned int vlen) { return errno = ENOSYS, -1; #endif } + +ssize_t +uv__fs_copy_file_range(int fd_in, + off_t* off_in, + int fd_out, + off_t* off_out, + size_t len, + unsigned int flags) +{ +#if __FreeBSD__ >= 13 && !defined(__DragonFly__) + return copy_file_range(fd_in, off_in, fd_out, off_out, len, flags); +#else + return errno = ENOSYS, -1; +#endif +} diff --git a/Utilities/cmlibuv/src/unix/fs.c b/Utilities/cmlibuv/src/unix/fs.c index 40448f1..e2db3ad 100644 --- a/Utilities/cmlibuv/src/unix/fs.c +++ b/Utilities/cmlibuv/src/unix/fs.c @@ -247,7 +247,8 @@ UV_UNUSED(static struct timeval uv__fs_to_timeval(double time)) { static ssize_t uv__fs_futime(uv_fs_t* req) { #if defined(__linux__) \ || defined(_AIX71) \ - || defined(__HAIKU__) + || defined(__HAIKU__) \ + || defined(__GNU__) struct timespec ts[2]; ts[0] = uv__fs_to_timespec(req->atime); ts[1] = uv__fs_to_timespec(req->mtime); @@ -1085,6 +1086,17 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) { */ #if defined(__FreeBSD__) || defined(__DragonFly__) +#if defined(__FreeBSD__) + off_t off; + + off = req->off; + r = uv__fs_copy_file_range(in_fd, &off, out_fd, NULL, req->bufsml[0].len, 0); + if (r >= 0) { + r = off - req->off; + req->off = off; + return r; + } +#endif len = 0; r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0); #elif defined(__FreeBSD_kernel__) @@ -1179,7 +1191,9 @@ static ssize_t uv__fs_lutime(uv_fs_t* req) { #if defined(__linux__) || \ defined(_AIX71) || \ defined(__sun) || \ - defined(__HAIKU__) + defined(__HAIKU__) || \ + defined(__GNU__) || \ + defined(__OpenBSD__) struct timespec ts[2]; ts[0] = uv__fs_to_timespec(req->atime); ts[1] = uv__fs_to_timespec(req->mtime); diff --git a/Utilities/cmlibuv/src/unix/hurd.c b/Utilities/cmlibuv/src/unix/hurd.c new file mode 100644 index 0000000..d19ea63 --- /dev/null +++ b/Utilities/cmlibuv/src/unix/hurd.c @@ -0,0 +1,167 @@ +/* Copyright libuv project contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#define _GNU_SOURCE 1 + +#include "uv.h" +#include "internal.h" + +#include <hurd.h> +#include <hurd/process.h> +#include <mach/task_info.h> +#include <mach/vm_statistics.h> +#include <mach/vm_param.h> + +#include <inttypes.h> +#include <stddef.h> +#include <unistd.h> +#include <string.h> +#include <limits.h> + +int uv_exepath(char* buffer, size_t* size) { + kern_return_t err; + /* XXX in current Hurd, strings are char arrays of 1024 elements */ + string_t exepath; + ssize_t copied; + + if (buffer == NULL || size == NULL || *size == 0) + return UV_EINVAL; + + if (*size - 1 > 0) { + /* XXX limited length of buffer in current Hurd, this API will probably + * evolve in the future */ + err = proc_get_exe(getproc(), getpid(), exepath); + + if (err) + return UV__ERR(err); + } + + copied = uv__strscpy(buffer, exepath, *size); + + /* do not return error on UV_E2BIG failure */ + *size = copied < 0 ? strlen(buffer) : (size_t) copied; + + return 0; +} + +int uv_resident_set_memory(size_t* rss) { + kern_return_t err; + struct task_basic_info bi; + mach_msg_type_number_t count; + + count = TASK_BASIC_INFO_COUNT; + err = task_info(mach_task_self(), TASK_BASIC_INFO, + (task_info_t) &bi, &count); + + if (err) + return UV__ERR(err); + + *rss = bi.resident_size; + + return 0; +} + +uint64_t uv_get_free_memory(void) { + kern_return_t err; + struct vm_statistics vmstats; + + err = vm_statistics(mach_task_self(), &vmstats); + + if (err) + return 0; + + return vmstats.free_count * vm_page_size; +} + + +uint64_t uv_get_total_memory(void) { + kern_return_t err; + host_basic_info_data_t hbi; + mach_msg_type_number_t cnt; + + cnt = HOST_BASIC_INFO_COUNT; + err = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); + + if (err) + return 0; + + return hbi.memory_size; +} + + +int uv_uptime(double* uptime) { + char buf[128]; + + /* Try /proc/uptime first */ + if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf))) + if (1 == sscanf(buf, "%lf", uptime)) + return 0; + + /* Reimplement here code from procfs to calculate uptime if not mounted? */ + + return UV__ERR(EIO); +} + +void uv_loadavg(double avg[3]) { + char buf[128]; /* Large enough to hold all of /proc/loadavg. */ + + if (0 == uv__slurp("/proc/loadavg", buf, sizeof(buf))) + if (3 == sscanf(buf, "%lf %lf %lf", &avg[0], &avg[1], &avg[2])) + return; + + /* Reimplement here code from procfs to calculate loadavg if not mounted? */ +} + + +int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { + kern_return_t err; + host_basic_info_data_t hbi; + mach_msg_type_number_t cnt; + + /* Get count of cpus */ + cnt = HOST_BASIC_INFO_COUNT; + err = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t) &hbi, &cnt); + + if (err) { + err = UV__ERR(err); + goto abort; + } + + /* XXX not implemented on the Hurd */ + *cpu_infos = uv__calloc(hbi.avail_cpus, sizeof(**cpu_infos)); + if (*cpu_infos == NULL) { + err = UV_ENOMEM; + goto abort; + } + + *count = hbi.avail_cpus; + + return 0; + + abort: + *cpu_infos = NULL; + *count = 0; + return err; +} + +uint64_t uv_get_constrained_memory(void) { + return 0; /* Memory constraints are unknown. */ +} diff --git a/Utilities/cmlibuv/src/unix/internal.h b/Utilities/cmlibuv/src/unix/internal.h index 586ae39..f41ee3c 100644 --- a/Utilities/cmlibuv/src/unix/internal.h +++ b/Utilities/cmlibuv/src/unix/internal.h @@ -155,7 +155,8 @@ typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t; /* loop flags */ enum { - UV_LOOP_BLOCK_SIGPROF = 1 + UV_LOOP_BLOCK_SIGPROF = 0x1, + UV_LOOP_REAP_CHILDREN = 0x2 }; /* flags of excluding ifaddr */ @@ -184,11 +185,9 @@ struct uv__stream_queued_fds_s { defined(__linux__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) -#define uv__cloexec uv__cloexec_ioctl #define uv__nonblock uv__nonblock_ioctl #define UV__NONBLOCK_IS_IOCTL 1 #else -#define uv__cloexec uv__cloexec_fcntl #define uv__nonblock uv__nonblock_fcntl #define UV__NONBLOCK_IS_IOCTL 0 #endif @@ -206,8 +205,7 @@ struct uv__stream_queued_fds_s { #endif /* core */ -int uv__cloexec_ioctl(int fd, int set); -int uv__cloexec_fcntl(int fd, int set); +int uv__cloexec(int fd, int set); int uv__nonblock_ioctl(int fd, int set); int uv__nonblock_fcntl(int fd, int set); int uv__close(int fd); /* preserves errno */ @@ -251,14 +249,15 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events); int uv__accept(int sockfd); int uv__dup2_cloexec(int oldfd, int newfd); int uv__open_cloexec(const char* path, int flags); +int uv__slurp(const char* filename, char* buf, size_t len); /* tcp */ -int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb); +int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb); int uv__tcp_nodelay(int fd, int on); int uv__tcp_keepalive(int fd, int on, unsigned int delay); /* pipe */ -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); +int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); /* signal */ void uv__signal_close(uv_signal_t* handle); @@ -288,10 +287,10 @@ void uv__tcp_close(uv_tcp_t* handle); size_t uv__thread_stack_size(void); void uv__udp_close(uv_udp_t* handle); void uv__udp_finish_close(uv_udp_t* handle); -uv_handle_type uv__handle_type(int fd); FILE* uv__open_file(const char* path); int uv__getpwuid_r(uv_passwd_t* pwd); int uv__search_path(const char* prog, char* buf, size_t* buflen); +void uv__wait_children(uv_loop_t* loop); /* random */ int uv__random_devurandom(void* buf, size_t buflen); @@ -366,5 +365,15 @@ size_t strnlen(const char* s, size_t maxlen); #endif #endif +#if defined(__FreeBSD__) +ssize_t +uv__fs_copy_file_range(int fd_in, + off_t* off_in, + int fd_out, + off_t* off_out, + size_t len, + unsigned int flags); +#endif + #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/Utilities/cmlibuv/src/unix/kqueue.c b/Utilities/cmlibuv/src/unix/kqueue.c index 75e9110..5dac76a 100644 --- a/Utilities/cmlibuv/src/unix/kqueue.c +++ b/Utilities/cmlibuv/src/unix/kqueue.c @@ -117,6 +117,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { unsigned int revents; QUEUE* q; uv__io_t* w; + uv_process_t* process; sigset_t* pset; sigset_t set; uint64_t base; @@ -285,6 +286,21 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { for (i = 0; i < nfds; i++) { ev = events + i; fd = ev->ident; + + /* Handle kevent NOTE_EXIT results */ + if (ev->filter == EVFILT_PROC) { + QUEUE_FOREACH(q, &loop->process_handles) { + process = QUEUE_DATA(q, uv_process_t, queue); + if (process->pid == fd) { + process->flags |= UV_HANDLE_REAP; + loop->flags |= UV_LOOP_REAP_CHILDREN; + break; + } + } + nevents++; + continue; + } + /* Skip invalidated events, see uv__platform_invalidate_fd */ if (fd == -1) continue; @@ -377,6 +393,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { nevents++; } + if (loop->flags & UV_LOOP_REAP_CHILDREN) { + loop->flags &= ~UV_LOOP_REAP_CHILDREN; + uv__wait_children(loop); + } + if (reset_timeout != 0) { timeout = user_timeout; reset_timeout = 0; @@ -435,7 +456,7 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) { /* Invalidate events with same file descriptor */ for (i = 0; i < nfds; i++) - if ((int) events[i].ident == fd) + if ((int) events[i].ident == fd && events[i].filter != EVFILT_PROC) events[i].ident = -1; } diff --git a/Utilities/cmlibuv/src/unix/linux-core.c b/Utilities/cmlibuv/src/unix/linux-core.c index 7b041e6..23a7daf 100644 --- a/Utilities/cmlibuv/src/unix/linux-core.c +++ b/Utilities/cmlibuv/src/unix/linux-core.c @@ -211,31 +211,6 @@ err: return UV_EINVAL; } -static int uv__slurp(const char* filename, char* buf, size_t len) { - ssize_t n; - int fd; - - assert(len > 0); - - fd = uv__open_cloexec(filename, O_RDONLY); - if (fd < 0) - return fd; - - do - n = read(fd, buf, len - 1); - while (n == -1 && errno == EINTR); - - if (uv__close_nocheckstdio(fd)) - abort(); - - if (n < 0) - return UV__ERR(errno); - - buf[n] = '\0'; - - return 0; -} - int uv_uptime(double* uptime) { static volatile int no_clock_boottime; char buf[128]; @@ -243,7 +218,7 @@ int uv_uptime(double* uptime) { int r; /* Try /proc/uptime first, then fallback to clock_gettime(). */ - + if (0 == uv__slurp("/proc/uptime", buf, sizeof(buf))) if (1 == sscanf(buf, "%lf", uptime)) return 0; @@ -641,6 +616,7 @@ static uint64_t read_cpufreq(unsigned int cpunum) { } +#ifdef HAVE_IFADDRS_H static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING))) return 1; @@ -654,6 +630,7 @@ static int uv__ifaddr_exclude(struct ifaddrs *ent, int exclude_type) { return exclude_type; return !exclude_type; } +#endif int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { #ifndef HAVE_IFADDRS_H diff --git a/Utilities/cmlibuv/src/unix/os390-syscalls.c b/Utilities/cmlibuv/src/unix/os390-syscalls.c index a741127..5861aaa 100644 --- a/Utilities/cmlibuv/src/unix/os390-syscalls.c +++ b/Utilities/cmlibuv/src/unix/os390-syscalls.c @@ -284,6 +284,8 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, nmsgsfds_t size; struct pollfd* pfds; int pollret; + int pollfdret; + int pollmsgret; int reventcount; int nevents; struct pollfd msg_fd; @@ -304,24 +306,24 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, return -1; } - if (lst->size > 0) - _SET_FDS_MSGS(size, 1, lst->size - 1); - else - _SET_FDS_MSGS(size, 0, 0); + assert(lst->size > 0); + _SET_FDS_MSGS(size, 1, lst->size - 1); pfds = lst->items; pollret = poll(pfds, size, timeout); if (pollret <= 0) return pollret; - assert(lst->size > 0); - - pollret = _NFDS(pollret) + _NMSGS(pollret); + pollfdret = _NFDS(pollret); + pollmsgret = _NMSGS(pollret); reventcount = 0; nevents = 0; - msg_fd = pfds[lst->size - 1]; + msg_fd = pfds[lst->size - 1]; /* message queue is always last entry */ + maxevents = maxevents - pollmsgret; /* allow spot for message queue */ for (i = 0; - i < lst->size && i < maxevents && reventcount < pollret; ++i) { + i < lst->size - 1 && + nevents < maxevents && + reventcount < pollfdret; ++i) { struct epoll_event ev; struct pollfd* pfd; @@ -332,18 +334,18 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, ev.fd = pfd->fd; ev.events = pfd->revents; ev.is_msg = 0; - if (pfd->revents & POLLIN && pfd->revents & POLLOUT) - reventcount += 2; - else if (pfd->revents & (POLLIN | POLLOUT)) - ++reventcount; - pfd->revents = 0; + reventcount++; events[nevents++] = ev; } - if (msg_fd.revents != 0 && msg_fd.fd != -1) - if (i == lst->size) - events[nevents - 1].is_msg = 1; + if (pollmsgret > 0 && msg_fd.revents != 0 && msg_fd.fd != -1) { + struct epoll_event ev; + ev.fd = msg_fd.fd; + ev.events = msg_fd.revents; + ev.is_msg = 1; + events[nevents++] = ev; + } return nevents; } diff --git a/Utilities/cmlibuv/src/unix/os390.c b/Utilities/cmlibuv/src/unix/os390.c index bf0448b..3b16318 100644 --- a/Utilities/cmlibuv/src/unix/os390.c +++ b/Utilities/cmlibuv/src/unix/os390.c @@ -278,7 +278,9 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses, __net_ifconf6header_t ifc; __net_ifconf6entry_t* ifr; __net_ifconf6entry_t* p; - __net_ifconf6entry_t flg; + unsigned int i; + int count_names; + unsigned char netmask[16] = {0}; *count = 0; /* Assume maximum buffer size allowable */ @@ -287,24 +289,33 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses, if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) return UV__ERR(errno); + ifc.__nif6h_buffer = uv__calloc(1, maxsize); + + if (ifc.__nif6h_buffer == NULL) { + uv__close(sockfd); + return UV_ENOMEM; + } + ifc.__nif6h_version = 1; ifc.__nif6h_buflen = maxsize; - ifc.__nif6h_buffer = uv__calloc(1, maxsize);; if (ioctl(sockfd, SIOCGIFCONF6, &ifc) == -1) { + /* This will error on a system that does not support IPv6. However, we want + * to treat this as there being 0 interfaces so we can continue to get IPv4 + * interfaces in uv_interface_addresses(). So return 0 instead of the error. + */ + uv__free(ifc.__nif6h_buffer); uv__close(sockfd); - return UV__ERR(errno); + errno = 0; + return 0; } - - *count = 0; ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { p = ifr; ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); - if (!(p->__nif6e_addr.sin6_family == AF_INET6 || - p->__nif6e_addr.sin6_family == AF_INET)) + if (!(p->__nif6e_addr.sin6_family == AF_INET6)) continue; if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) @@ -313,21 +324,28 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses, ++(*count); } + if ((*count) == 0) { + uv__free(ifc.__nif6h_buffer); + uv__close(sockfd); + return 0; + } + /* Alloc the return interface structs */ - *addresses = uv__malloc(*count * sizeof(uv_interface_address_t)); + *addresses = uv__calloc(1, *count * sizeof(uv_interface_address_t)); if (!(*addresses)) { + uv__free(ifc.__nif6h_buffer); uv__close(sockfd); return UV_ENOMEM; } address = *addresses; + count_names = 0; ifr = (__net_ifconf6entry_t*)(ifc.__nif6h_buffer); while ((char*)ifr < (char*)ifc.__nif6h_buffer + ifc.__nif6h_buflen) { p = ifr; ifr = (__net_ifconf6entry_t*)((char*)ifr + ifc.__nif6h_entrylen); - if (!(p->__nif6e_addr.sin6_family == AF_INET6 || - p->__nif6e_addr.sin6_family == AF_INET)) + if (!(p->__nif6e_addr.sin6_family == AF_INET6)) continue; if (!(p->__nif6e_flags & _NIF6E_FLAGS_ON_LINK_ACTIVE)) @@ -335,20 +353,41 @@ static int uv__interface_addresses_v6(uv_interface_address_t** addresses, /* All conditions above must match count loop */ - address->name = uv__strdup(p->__nif6e_name); + i = 0; + /* Ignore EBCDIC space (0x40) padding in name */ + while (i < ARRAY_SIZE(p->__nif6e_name) && + p->__nif6e_name[i] != 0x40 && + p->__nif6e_name[i] != 0) + ++i; + address->name = uv__malloc(i + 1); + if (address->name == NULL) { + uv_free_interface_addresses(*addresses, count_names); + uv__free(ifc.__nif6h_buffer); + uv__close(sockfd); + return UV_ENOMEM; + } + memcpy(address->name, p->__nif6e_name, i); + address->name[i] = '\0'; + __e2a_s(address->name); + count_names++; - if (p->__nif6e_addr.sin6_family == AF_INET6) - address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr); - else - address->address.address4 = *((struct sockaddr_in*) &p->__nif6e_addr); + address->address.address6 = *((struct sockaddr_in6*) &p->__nif6e_addr); - /* TODO: Retrieve netmask using SIOCGIFNETMASK ioctl */ + for (i = 0; i < (p->__nif6e_prefixlen / 8); i++) + netmask[i] = 0xFF; - address->is_internal = flg.__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0; - memset(address->phys_addr, 0, sizeof(address->phys_addr)); + if (p->__nif6e_prefixlen % 8) + netmask[i] = 0xFF << (8 - (p->__nif6e_prefixlen % 8)); + + address->netmask.netmask6.sin6_len = p->__nif6e_prefixlen; + memcpy(&(address->netmask.netmask6.sin6_addr), netmask, 16); + address->netmask.netmask6.sin6_family = AF_INET6; + + address->is_internal = p->__nif6e_flags & _NIF6E_FLAGS_LOOPBACK ? 1 : 0; address++; } + uv__free(ifc.__nif6h_buffer); uv__close(sockfd); return 0; } @@ -362,14 +401,18 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { struct ifreq flg; struct ifreq* ifr; struct ifreq* p; + uv_interface_address_t* addresses_v6; int count_v6; + unsigned int i; + int rc; + int count_names; *count = 0; *addresses = NULL; /* get the ipv6 addresses first */ - uv_interface_address_t* addresses_v6; - uv__interface_addresses_v6(&addresses_v6, &count_v6); + if ((rc = uv__interface_addresses_v6(&addresses_v6, &count_v6)) != 0) + return rc; /* now get the ipv4 addresses */ @@ -377,12 +420,27 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { maxsize = 16384; sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (0 > sockfd) + if (0 > sockfd) { + if (count_v6) + uv_free_interface_addresses(addresses_v6, count_v6); return UV__ERR(errno); + } ifc.ifc_req = uv__calloc(1, maxsize); + + if (ifc.ifc_req == NULL) { + if (count_v6) + uv_free_interface_addresses(addresses_v6, count_v6); + uv__close(sockfd); + return UV_ENOMEM; + } + ifc.ifc_len = maxsize; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { + if (count_v6) + uv_free_interface_addresses(addresses_v6, count_v6); + uv__free(ifc.ifc_req); uv__close(sockfd); return UV__ERR(errno); } @@ -403,6 +461,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { + if (count_v6) + uv_free_interface_addresses(addresses_v6, count_v6); + uv__free(ifc.ifc_req); uv__close(sockfd); return UV__ERR(errno); } @@ -413,27 +474,35 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { (*count)++; } - if (*count == 0) { + if (*count == 0 && count_v6 == 0) { + uv__free(ifc.ifc_req); uv__close(sockfd); return 0; } /* Alloc the return interface structs */ - *addresses = uv__malloc((*count + count_v6) * + *addresses = uv__calloc(1, (*count + count_v6) * sizeof(uv_interface_address_t)); if (!(*addresses)) { + if (count_v6) + uv_free_interface_addresses(addresses_v6, count_v6); + uv__free(ifc.ifc_req); uv__close(sockfd); return UV_ENOMEM; } address = *addresses; - /* copy over the ipv6 addresses */ - memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t)); - address += count_v6; - *count += count_v6; - uv__free(addresses_v6); + /* copy over the ipv6 addresses if any are found */ + if (count_v6) { + memcpy(address, addresses_v6, count_v6 * sizeof(uv_interface_address_t)); + address += count_v6; + *count += count_v6; + /* free ipv6 addresses, but keep address names */ + uv__free(addresses_v6); + } + count_names = *count; ifr = ifc.ifc_req; while ((char*)ifr < (char*)ifc.ifc_req + ifc.ifc_len) { p = ifr; @@ -446,6 +515,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { + uv_free_interface_addresses(*addresses, count_names); + uv__free(ifc.ifc_req); uv__close(sockfd); return UV_ENOSYS; } @@ -455,22 +526,43 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { /* All conditions above must match count loop */ - address->name = uv__strdup(p->ifr_name); + i = 0; + /* Ignore EBCDIC space (0x40) padding in name */ + while (i < ARRAY_SIZE(p->ifr_name) && + p->ifr_name[i] != 0x40 && + p->ifr_name[i] != 0) + ++i; + address->name = uv__malloc(i + 1); + if (address->name == NULL) { + uv_free_interface_addresses(*addresses, count_names); + uv__free(ifc.ifc_req); + uv__close(sockfd); + return UV_ENOMEM; + } + memcpy(address->name, p->ifr_name, i); + address->name[i] = '\0'; + __e2a_s(address->name); + count_names++; + + address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); - if (p->ifr_addr.sa_family == AF_INET6) { - address->address.address6 = *((struct sockaddr_in6*) &p->ifr_addr); - } else { - address->address.address4 = *((struct sockaddr_in*) &p->ifr_addr); + if (ioctl(sockfd, SIOCGIFNETMASK, p) == -1) { + uv_free_interface_addresses(*addresses, count_names); + uv__free(ifc.ifc_req); + uv__close(sockfd); + return UV__ERR(errno); } + address->netmask.netmask4 = *((struct sockaddr_in*) &p->ifr_addr); + address->netmask.netmask4.sin_family = AF_INET; address->is_internal = flg.ifr_flags & IFF_LOOPBACK ? 1 : 0; - memset(address->phys_addr, 0, sizeof(address->phys_addr)); address++; } #undef ADDR_SIZE #undef MAX + uv__free(ifc.ifc_req); uv__close(sockfd); return 0; } @@ -529,27 +621,17 @@ int uv__io_check_fd(uv_loop_t* loop, int fd) { } -void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); -} - - int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); return 0; } -int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, - const char* filename, unsigned int flags) { +static int os390_regfileint(uv_fs_event_t* handle, char* path) { uv__os390_epoll* ep; _RFIS reg_struct; - char* path; int rc; - if (uv__is_active(handle)) - return UV_EINVAL; - ep = handle->loop->ep; assert(ep->msg_queue != -1); @@ -558,25 +640,44 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, reg_struct.__rfis_type = 1; memcpy(reg_struct.__rfis_utok, &handle, sizeof(handle)); + rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct); + if (rc != 0) + return UV__ERR(errno); + + memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok, + sizeof(handle->rfis_rftok)); + + return 0; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, + const char* filename, unsigned int flags) { + char* path; + int rc; + + if (uv__is_active(handle)) + return UV_EINVAL; + path = uv__strdup(filename); if (path == NULL) return UV_ENOMEM; - rc = __w_pioctl(path, _IOCC_REGFILEINT, sizeof(reg_struct), ®_struct); - if (rc != 0) - return UV__ERR(errno); + rc = os390_regfileint(handle, path); + if (rc != 0) { + uv__free(path); + return rc; + } uv__handle_start(handle); handle->path = path; handle->cb = cb; - memcpy(handle->rfis_rftok, reg_struct.__rfis_rftok, - sizeof(handle->rfis_rftok)); return 0; } -int uv_fs_event_stop(uv_fs_event_t* handle) { +int uv__fs_event_stop(uv_fs_event_t* handle) { uv__os390_epoll* ep; _RFIS reg_struct; int rc; @@ -602,12 +703,40 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { if (rc != 0 && errno != EALREADY && errno != ENOENT) abort(); + if (handle->path != NULL) { + uv__free(handle->path); + handle->path = NULL; + } + + if (rc != 0 && errno == EALREADY) + return -1; + uv__handle_stop(handle); return 0; } +int uv_fs_event_stop(uv_fs_event_t* handle) { + uv__fs_event_stop(handle); + return 0; +} + + +void uv__fs_event_close(uv_fs_event_t* handle) { + /* + * If we were unable to unregister file interest here, then it is most likely + * that there is a pending queued change notification. When this happens, we + * don't want to complete the close as it will free the underlying memory for + * the handle, causing a use-after-free problem when the event is processed. + * We defer the final cleanup until after the event is consumed in + * os390_message_queue_handler(). + */ + if (uv__fs_event_stop(handle) == 0) + uv__make_close_pending((uv_handle_t*) handle); +} + + static int os390_message_queue_handler(uv__os390_epoll* ep) { uv_fs_event_t* handle; int msglen; @@ -628,7 +757,15 @@ static int os390_message_queue_handler(uv__os390_epoll* ep) { events = 0; if (msg.__rfim_event == _RFIM_ATTR || msg.__rfim_event == _RFIM_WRITE) events = UV_CHANGE; - else if (msg.__rfim_event == _RFIM_RENAME) + else if (msg.__rfim_event == _RFIM_RENAME || msg.__rfim_event == _RFIM_UNLINK) + events = UV_RENAME; + else if (msg.__rfim_event == 156) + /* TODO(gabylb): zos - this event should not happen, need to investigate. + * + * This event seems to occur when the watched file is [re]moved, or an + * editor (like vim) renames then creates the file on save (for vim, that's + * when backupcopy=no|auto). + */ events = UV_RENAME; else /* Some event that we are not interested in. */ @@ -639,6 +776,26 @@ static int os390_message_queue_handler(uv__os390_epoll* ep) { */ __a2e_l(msg.__rfim_utok, sizeof(msg.__rfim_utok)); handle = *(uv_fs_event_t**)(msg.__rfim_utok); + assert(handle != NULL); + + assert((handle->flags & UV_HANDLE_CLOSED) == 0); + if (uv__is_closing(handle)) { + uv__handle_stop(handle); + uv__make_close_pending((uv_handle_t*) handle); + return 0; + } else if (handle->path == NULL) { + /* _RFIS_UNREG returned EALREADY. */ + uv__handle_stop(handle); + return 0; + } + + /* The file is implicitly unregistered when the change notification is + * sent, only one notification is sent per registration. So we need to + * re-register interest in a file after each change notification we + * receive. + */ + assert(handle->path != NULL); + os390_regfileint(handle, handle->path); handle->cb(handle, uv__basename_r(handle->path), events, 0); return 1; } @@ -650,6 +807,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { struct epoll_event* pe; struct epoll_event e; uv__os390_epoll* ep; + int have_signals; int real_timeout; QUEUE* q; uv__io_t* w; @@ -712,6 +870,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { count = 48; /* Benchmarks suggest this gives the best throughput. */ real_timeout = timeout; int nevents = 0; + have_signals = 0; if (uv__get_internal_fields(loop)->flags & UV_METRICS_IDLE_TIME) { reset_timeout = 1; @@ -796,6 +955,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { ep = loop->ep; if (pe->is_msg) { os390_message_queue_handler(ep); + nevents++; continue; } @@ -825,19 +985,35 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { pe->events |= w->pevents & (POLLIN | POLLOUT); if (pe->events != 0) { - uv__metrics_update_idle_time(loop); - w->cb(loop, w, pe->events); + /* Run signal watchers last. This also affects child process watchers + * because those are implemented in terms of signal watchers. + */ + if (w == &loop->signal_io_watcher) { + have_signals = 1; + } else { + uv__metrics_update_idle_time(loop); + w->cb(loop, w, pe->events); + } nevents++; } } - loop->watchers[loop->nwatchers] = NULL; - loop->watchers[loop->nwatchers + 1] = NULL; if (reset_timeout != 0) { timeout = user_timeout; reset_timeout = 0; } + if (have_signals != 0) { + uv__metrics_update_idle_time(loop); + loop->signal_io_watcher.cb(loop, &loop->signal_io_watcher, POLLIN); + } + + loop->watchers[loop->nwatchers] = NULL; + loop->watchers[loop->nwatchers + 1] = NULL; + + if (have_signals != 0) + return; /* Event loop should cycle now so don't poll again. */ + if (nevents != 0) { if (nfds == ARRAY_SIZE(events) && --count != 0) { /* Poll for more events but don't block this time. */ @@ -872,6 +1048,5 @@ int uv__io_fork(uv_loop_t* loop) { */ loop->ep = NULL; - uv__platform_loop_delete(loop); return uv__platform_loop_init(loop); } diff --git a/Utilities/cmlibuv/src/unix/pipe.c b/Utilities/cmlibuv/src/unix/pipe.c index fc7c4ea..e9b88c1 100644 --- a/Utilities/cmlibuv/src/unix/pipe.c +++ b/Utilities/cmlibuv/src/unix/pipe.c @@ -49,7 +49,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { /* Already bound? */ if (uv__stream_fd(handle) >= 0) return UV_EINVAL; - + if (uv__is_closing(handle)) { + return UV_EINVAL; + } /* Make a copy of the file name, it outlives this function's scope. */ pipe_fname = uv__strdup(name); if (pipe_fname == NULL) @@ -89,7 +91,7 @@ err_socket: } -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { +int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { if (uv__stream_fd(handle) == -1) return UV_EINVAL; @@ -317,7 +319,7 @@ uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { if (handle->accepted_fd == -1) return UV_UNKNOWN_HANDLE; else - return uv__handle_type(handle->accepted_fd); + return uv_guess_handle(handle->accepted_fd); } diff --git a/Utilities/cmlibuv/src/unix/process.c b/Utilities/cmlibuv/src/unix/process.c index 2af2088..0de5c46 100644 --- a/Utilities/cmlibuv/src/unix/process.c +++ b/Utilities/cmlibuv/src/unix/process.c @@ -27,6 +27,7 @@ #include <assert.h> #include <errno.h> #include <signal.h> +#include <string.h> #include <sys/types.h> #include <sys/wait.h> @@ -35,9 +36,22 @@ #include <poll.h> #include <sched.h> -#if defined(__APPLE__) && !TARGET_OS_IPHONE +#if defined(__APPLE__) +# include <spawn.h> +# include <paths.h> +# include <sys/kauth.h> +# include <sys/types.h> +# include <sys/sysctl.h> +# include <dlfcn.h> # include <crt_externs.h> +# include <xlocale.h> # define environ (*_NSGetEnviron()) + +/* macOS 10.14 back does not define this constant */ +# ifndef POSIX_SPAWN_SETSID +# define POSIX_SPAWN_SETSID 1024 +# endif + #else extern char **environ; #endif @@ -61,21 +75,35 @@ extern char **environ; #endif #endif +#if defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__OpenBSD__) +#include <sys/event.h> +#else +#define UV_USE_SIGCHLD +#endif + +#ifdef UV_USE_SIGCHLD static void uv__chld(uv_signal_t* handle, int signum) { + assert(signum == SIGCHLD); + uv__wait_children(handle->loop); +} +#endif + +void uv__wait_children(uv_loop_t* loop) { uv_process_t* process; - uv_loop_t* loop; int exit_status; int term_signal; int status; + int options; pid_t pid; QUEUE pending; QUEUE* q; QUEUE* h; - assert(signum == SIGCHLD); - QUEUE_INIT(&pending); - loop = handle->loop; h = &loop->process_handles; q = QUEUE_HEAD(h); @@ -83,19 +111,33 @@ static void uv__chld(uv_signal_t* handle, int signum) { process = QUEUE_DATA(q, uv_process_t, queue); q = QUEUE_NEXT(q); +#ifndef UV_USE_SIGCHLD + if ((process->flags & UV_HANDLE_REAP) == 0) + continue; + options = 0; + process->flags &= ~UV_HANDLE_REAP; +#else + options = WNOHANG; +#endif + do - pid = waitpid(process->pid, &status, WNOHANG); + pid = waitpid(process->pid, &status, options); while (pid == -1 && errno == EINTR); - if (pid == 0) +#ifdef UV_USE_SIGCHLD + if (pid == 0) /* Not yet exited */ continue; +#endif if (pid == -1) { if (errno != ECHILD) abort(); + /* The child died, and we missed it. This probably means someone else + * stole the waitpid from us. Handle this by not handling it at all. */ continue; } + assert(pid == process->pid); process->status = status; QUEUE_REMOVE(&process->queue); QUEUE_INSERT_TAIL(&pending, &process->queue); @@ -206,16 +248,14 @@ static void uv__write_int(int fd, int val) { n = write(fd, &val, sizeof(val)); while (n == -1 && errno == EINTR); - if (n == -1 && errno == EPIPE) - return; /* parent process has quit */ - - assert(n == sizeof(val)); + /* The write might have failed (e.g. if the parent process has died), + * but we have nothing left but to _exit ourself now too. */ + _exit(127); } static void uv__write_errno(int error_fd) { uv__write_int(error_fd, UV__ERR(errno)); - _exit(127); } @@ -273,22 +313,31 @@ static void uv__process_child_init(const uv_process_options_t* options, use_fd = pipes[fd][1]; if (use_fd < 0 || use_fd >= fd) continue; +#ifdef F_DUPFD_CLOEXEC /* POSIX 2008 */ + pipes[fd][1] = fcntl(use_fd, F_DUPFD_CLOEXEC, stdio_count); +#else pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count); +#endif if (pipes[fd][1] == -1) uv__write_errno(error_fd); +#ifndef F_DUPFD_CLOEXEC /* POSIX 2008 */ + n = uv__cloexec(pipes[fd][1], 1); + if (n) + uv__write_int(error_fd, n); +#endif } for (fd = 0; fd < stdio_count; fd++) { - close_fd = pipes[fd][0]; + close_fd = -1; use_fd = pipes[fd][1]; if (use_fd < 0) { if (fd >= 3) continue; else { - /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is - * set - */ + /* Redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is + * set. */ + uv__close_nocheckstdio(fd); /* Free up fd, if it happens to be open. */ use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR); close_fd = use_fd; @@ -297,28 +346,27 @@ static void uv__process_child_init(const uv_process_options_t* options, } } - if (fd == use_fd) - uv__cloexec_fcntl(use_fd, 0); - else + if (fd == use_fd) { + if (close_fd == -1) { + n = uv__cloexec(use_fd, 0); + if (n) + uv__write_int(error_fd, n); + } + } + else { fd = dup2(use_fd, fd); + } if (fd == -1) uv__write_errno(error_fd); - if (fd <= 2) + if (fd <= 2 && close_fd == -1) uv__nonblock_fcntl(fd, 0); if (close_fd >= stdio_count) uv__close(close_fd); } - for (fd = 0; fd < stdio_count; fd++) { - use_fd = pipes[fd][1]; - - if (use_fd >= stdio_count) - uv__close(use_fd); - } - if (options->cwd != NULL && chdir(options->cwd)) uv__write_errno(error_fd); @@ -361,9 +409,8 @@ static void uv__process_child_init(const uv_process_options_t* options, #endif #endif - if (options->env != NULL) { + if (options->env != NULL) environ = options->env; - } /* Reset signal mask just before exec. */ sigemptyset(&signewset); @@ -377,11 +424,555 @@ static void uv__process_child_init(const uv_process_options_t* options, #endif uv__write_errno(error_fd); - abort(); } #endif +#if defined(__APPLE__) +typedef struct uv__posix_spawn_fncs_tag { + struct { + int (*addchdir_np)(const posix_spawn_file_actions_t *, const char *); + } file_actions; +} uv__posix_spawn_fncs_t; + + +static uv_once_t posix_spawn_init_once = UV_ONCE_INIT; +static uv__posix_spawn_fncs_t posix_spawn_fncs; +static int posix_spawn_can_use_setsid; + + +static void uv__spawn_init_posix_spawn_fncs(void) { + /* Try to locate all non-portable functions at runtime */ + posix_spawn_fncs.file_actions.addchdir_np = + dlsym(RTLD_DEFAULT, "posix_spawn_file_actions_addchdir_np"); +} + + +static void uv__spawn_init_can_use_setsid(void) { + int which[] = {CTL_KERN, KERN_OSRELEASE}; + unsigned major; + unsigned minor; + unsigned patch; + char buf[256]; + size_t len; + + len = sizeof(buf); + if (sysctl(which, ARRAY_SIZE(which), buf, &len, NULL, 0)) + return; + + /* NULL specifies to use LC_C_LOCALE */ + if (3 != sscanf_l(buf, NULL, "%u.%u.%u", &major, &minor, &patch)) + return; + + posix_spawn_can_use_setsid = (major >= 19); /* macOS Catalina */ +} + + +static void uv__spawn_init_posix_spawn(void) { + /* Init handles to all potentially non-defined functions */ + uv__spawn_init_posix_spawn_fncs(); + + /* Init feature detection for POSIX_SPAWN_SETSID flag */ + uv__spawn_init_can_use_setsid(); +} + + +static int uv__spawn_set_posix_spawn_attrs( + posix_spawnattr_t* attrs, + const uv__posix_spawn_fncs_t* posix_spawn_fncs, + const uv_process_options_t* options) { + int err; + unsigned int flags; + sigset_t signal_set; + + err = posix_spawnattr_init(attrs); + if (err != 0) { + /* If initialization fails, no need to de-init, just return */ + return err; + } + + if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) { + /* kauth_cred_issuser currently requires exactly uid == 0 for these + * posixspawn_attrs (set_groups_np, setuid_np, setgid_np), which deviates + * from the normal specification of setuid (which also uses euid), and they + * are also undocumented syscalls, so we do not use them. */ + err = ENOSYS; + goto error; + } + + /* Set flags for spawn behavior + * 1) POSIX_SPAWN_CLOEXEC_DEFAULT: (Apple Extension) All descriptors in the + * parent will be treated as if they had been created with O_CLOEXEC. The + * only fds that will be passed on to the child are those manipulated by + * the file actions + * 2) POSIX_SPAWN_SETSIGDEF: Signals mentioned in spawn-sigdefault in the + * spawn attributes will be reset to behave as their default + * 3) POSIX_SPAWN_SETSIGMASK: Signal mask will be set to the value of + * spawn-sigmask in attributes + * 4) POSIX_SPAWN_SETSID: Make the process a new session leader if a detached + * session was requested. */ + flags = POSIX_SPAWN_CLOEXEC_DEFAULT | + POSIX_SPAWN_SETSIGDEF | + POSIX_SPAWN_SETSIGMASK; + if (options->flags & UV_PROCESS_DETACHED) { + /* If running on a version of macOS where this flag is not supported, + * revert back to the fork/exec flow. Otherwise posix_spawn will + * silently ignore the flag. */ + if (!posix_spawn_can_use_setsid) { + err = ENOSYS; + goto error; + } + + flags |= POSIX_SPAWN_SETSID; + } + err = posix_spawnattr_setflags(attrs, flags); + if (err != 0) + goto error; + + /* Reset all signal the child to their default behavior */ + sigfillset(&signal_set); + err = posix_spawnattr_setsigdefault(attrs, &signal_set); + if (err != 0) + goto error; + + /* Reset the signal mask for all signals */ + sigemptyset(&signal_set); + err = posix_spawnattr_setsigmask(attrs, &signal_set); + if (err != 0) + goto error; + + return err; + +error: + (void) posix_spawnattr_destroy(attrs); + return err; +} + + +static int uv__spawn_set_posix_spawn_file_actions( + posix_spawn_file_actions_t* actions, + const uv__posix_spawn_fncs_t* posix_spawn_fncs, + const uv_process_options_t* options, + int stdio_count, + int (*pipes)[2]) { + int fd; + int fd2; + int use_fd; + int err; + + err = posix_spawn_file_actions_init(actions); + if (err != 0) { + /* If initialization fails, no need to de-init, just return */ + return err; + } + + /* Set the current working directory if requested */ + if (options->cwd != NULL) { + if (posix_spawn_fncs->file_actions.addchdir_np == NULL) { + err = ENOSYS; + goto error; + } + + err = posix_spawn_fncs->file_actions.addchdir_np(actions, options->cwd); + if (err != 0) + goto error; + } + + /* Do not return ENOSYS after this point, as we may mutate pipes. */ + + /* First duplicate low numbered fds, since it's not safe to duplicate them, + * they could get replaced. Example: swapping stdout and stderr; without + * this fd 2 (stderr) would be duplicated into fd 1, thus making both + * stdout and stderr go to the same fd, which was not the intention. */ + for (fd = 0; fd < stdio_count; fd++) { + use_fd = pipes[fd][1]; + if (use_fd < 0 || use_fd >= fd) + continue; + use_fd = stdio_count; + for (fd2 = 0; fd2 < stdio_count; fd2++) { + /* If we were not setting POSIX_SPAWN_CLOEXEC_DEFAULT, we would need to + * also consider whether fcntl(fd, F_GETFD) returned without the + * FD_CLOEXEC flag set. */ + if (pipes[fd2][1] == use_fd) { + use_fd++; + fd2 = 0; + } + } + err = posix_spawn_file_actions_adddup2( + actions, + pipes[fd][1], + use_fd); + assert(err != ENOSYS); + if (err != 0) + goto error; + pipes[fd][1] = use_fd; + } + + /* Second, move the descriptors into their respective places */ + for (fd = 0; fd < stdio_count; fd++) { + use_fd = pipes[fd][1]; + if (use_fd < 0) { + if (fd >= 3) + continue; + else { + /* If ignored, redirect to (or from) /dev/null, */ + err = posix_spawn_file_actions_addopen( + actions, + fd, + "/dev/null", + fd == 0 ? O_RDONLY : O_RDWR, + 0); + assert(err != ENOSYS); + if (err != 0) + goto error; + continue; + } + } + + if (fd == use_fd) + err = posix_spawn_file_actions_addinherit_np(actions, fd); + else + err = posix_spawn_file_actions_adddup2(actions, use_fd, fd); + assert(err != ENOSYS); + if (err != 0) + goto error; + + /* Make sure the fd is marked as non-blocking (state shared between child + * and parent). */ + uv__nonblock_fcntl(use_fd, 0); + } + + /* Finally, close all the superfluous descriptors */ + for (fd = 0; fd < stdio_count; fd++) { + use_fd = pipes[fd][1]; + if (use_fd < stdio_count) + continue; + + /* Check if we already closed this. */ + for (fd2 = 0; fd2 < fd; fd2++) { + if (pipes[fd2][1] == use_fd) + break; + } + if (fd2 < fd) + continue; + + err = posix_spawn_file_actions_addclose(actions, use_fd); + assert(err != ENOSYS); + if (err != 0) + goto error; + } + + return 0; + +error: + (void) posix_spawn_file_actions_destroy(actions); + return err; +} + +char* uv__spawn_find_path_in_env(char** env) { + char** env_iterator; + const char path_var[] = "PATH="; + + /* Look for an environment variable called PATH in the + * provided env array, and return its value if found */ + for (env_iterator = env; *env_iterator != NULL; env_iterator++) { + if (strncmp(*env_iterator, path_var, sizeof(path_var) - 1) == 0) { + /* Found "PATH=" at the beginning of the string */ + return *env_iterator + sizeof(path_var) - 1; + } + } + + return NULL; +} + + +static int uv__spawn_resolve_and_spawn(const uv_process_options_t* options, + posix_spawnattr_t* attrs, + posix_spawn_file_actions_t* actions, + pid_t* pid) { + const char *p; + const char *z; + const char *path; + size_t l; + size_t k; + int err; + int seen_eacces; + + path = NULL; + err = -1; + seen_eacces = 0; + + /* Short circuit for erroneous case */ + if (options->file == NULL) + return ENOENT; + + /* The environment for the child process is that of the parent unless overriden + * by options->env */ + char** env = environ; + if (options->env != NULL) + env = options->env; + + /* If options->file contains a slash, posix_spawn/posix_spawnp should behave + * the same, and do not involve PATH resolution at all. The libc + * `posix_spawnp` provided by Apple is buggy (since 10.15), so we now emulate it + * here, per https://github.com/libuv/libuv/pull/3583. */ + if (strchr(options->file, '/') != NULL) { + do + err = posix_spawn(pid, options->file, actions, attrs, options->args, env); + while (err == EINTR); + return err; + } + + /* Look for the definition of PATH in the provided env */ + path = uv__spawn_find_path_in_env(env); + + /* The following resolution logic (execvpe emulation) is copied from + * https://git.musl-libc.org/cgit/musl/tree/src/process/execvp.c + * and adapted to work for our specific usage */ + + /* If no path was provided in env, use the default value + * to look for the executable */ + if (path == NULL) + path = _PATH_DEFPATH; + + k = strnlen(options->file, NAME_MAX + 1); + if (k > NAME_MAX) + return ENAMETOOLONG; + + l = strnlen(path, PATH_MAX - 1) + 1; + + for (p = path;; p = z) { + /* Compose the new process file from the entry in the PATH + * environment variable and the actual file name */ + char b[PATH_MAX + NAME_MAX]; + z = strchr(p, ':'); + if (!z) + z = p + strlen(p); + if ((size_t)(z - p) >= l) { + if (!*z++) + break; + + continue; + } + memcpy(b, p, z - p); + b[z - p] = '/'; + memcpy(b + (z - p) + (z > p), options->file, k + 1); + + /* Try to spawn the new process file. If it fails with ENOENT, the + * new process file is not in this PATH entry, continue with the next + * PATH entry. */ + do + err = posix_spawn(pid, b, actions, attrs, options->args, env); + while (err == EINTR); + + switch (err) { + case EACCES: + seen_eacces = 1; + break; /* continue search */ + case ENOENT: + case ENOTDIR: + break; /* continue search */ + default: + return err; + } + + if (!*z++) + break; + } + + if (seen_eacces) + return EACCES; + return err; +} + + +static int uv__spawn_and_init_child_posix_spawn( + const uv_process_options_t* options, + int stdio_count, + int (*pipes)[2], + pid_t* pid, + const uv__posix_spawn_fncs_t* posix_spawn_fncs) { + int err; + posix_spawnattr_t attrs; + posix_spawn_file_actions_t actions; + + err = uv__spawn_set_posix_spawn_attrs(&attrs, posix_spawn_fncs, options); + if (err != 0) + goto error; + + /* This may mutate pipes. */ + err = uv__spawn_set_posix_spawn_file_actions(&actions, + posix_spawn_fncs, + options, + stdio_count, + pipes); + if (err != 0) { + (void) posix_spawnattr_destroy(&attrs); + goto error; + } + + /* Try to spawn options->file resolving in the provided environment + * if any */ + err = uv__spawn_resolve_and_spawn(options, &attrs, &actions, pid); + assert(err != ENOSYS); + + /* Destroy the actions/attributes */ + (void) posix_spawn_file_actions_destroy(&actions); + (void) posix_spawnattr_destroy(&attrs); + +error: + /* In an error situation, the attributes and file actions are + * already destroyed, only the happy path requires cleanup */ + return UV__ERR(err); +} +#endif + +static int uv__spawn_and_init_child_fork(const uv_process_options_t* options, + int stdio_count, + int (*pipes)[2], + int error_fd, + pid_t* pid) { + sigset_t signewset; + sigset_t sigoldset; + + /* Start the child with most signals blocked, to avoid any issues before we + * can reset them, but allow program failures to exit (and not hang). */ + sigfillset(&signewset); + sigdelset(&signewset, SIGKILL); + sigdelset(&signewset, SIGSTOP); + sigdelset(&signewset, SIGTRAP); + sigdelset(&signewset, SIGSEGV); + sigdelset(&signewset, SIGBUS); + sigdelset(&signewset, SIGILL); + sigdelset(&signewset, SIGSYS); + sigdelset(&signewset, SIGABRT); + if (pthread_sigmask(SIG_BLOCK, &signewset, &sigoldset) != 0) + abort(); + + *pid = fork(); + + if (*pid == 0) { + /* Fork succeeded, in the child process */ + uv__process_child_init(options, stdio_count, pipes, error_fd); + abort(); + } + + if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0) + abort(); + + if (*pid == -1) + /* Failed to fork */ + return UV__ERR(errno); + + /* Fork succeeded, in the parent process */ + return 0; +} + +static int uv__spawn_and_init_child( + uv_loop_t* loop, + const uv_process_options_t* options, + int stdio_count, + int (*pipes)[2], + pid_t* pid) { + int signal_pipe[2] = { -1, -1 }; + int status; + int err; + int exec_errorno; + ssize_t r; + +#if defined(__APPLE__) + uv_once(&posix_spawn_init_once, uv__spawn_init_posix_spawn); + + /* Special child process spawn case for macOS Big Sur (11.0) onwards + * + * Big Sur introduced a significant performance degradation on a call to + * fork/exec when the process has many pages mmaped in with MAP_JIT, like, say + * a javascript interpreter. Electron-based applications, for example, + * are impacted; though the magnitude of the impact depends on how much the + * app relies on subprocesses. + * + * On macOS, though, posix_spawn is implemented in a way that does not + * exhibit the problem. This block implements the forking and preparation + * logic with posix_spawn and its related primitives. It also takes advantage of + * the macOS extension POSIX_SPAWN_CLOEXEC_DEFAULT that makes impossible to + * leak descriptors to the child process. */ + err = uv__spawn_and_init_child_posix_spawn(options, + stdio_count, + pipes, + pid, + &posix_spawn_fncs); + + /* The posix_spawn flow will return UV_ENOSYS if any of the posix_spawn_x_np + * non-standard functions is both _needed_ and _undefined_. In those cases, + * default back to the fork/execve strategy. For all other errors, just fail. */ + if (err != UV_ENOSYS) + return err; + +#endif + + /* This pipe is used by the parent to wait until + * the child has called `execve()`. We need this + * to avoid the following race condition: + * + * if ((pid = fork()) > 0) { + * kill(pid, SIGTERM); + * } + * else if (pid == 0) { + * execve("/bin/cat", argp, envp); + * } + * + * The parent sends a signal immediately after forking. + * Since the child may not have called `execve()` yet, + * there is no telling what process receives the signal, + * our fork or /bin/cat. + * + * To avoid ambiguity, we create a pipe with both ends + * marked close-on-exec. Then, after the call to `fork()`, + * the parent polls the read end until it EOFs or errors with EPIPE. + */ + err = uv__make_pipe(signal_pipe, 0); + if (err) + return err; + + /* Acquire write lock to prevent opening new fds in worker threads */ + uv_rwlock_wrlock(&loop->cloexec_lock); + + err = uv__spawn_and_init_child_fork(options, stdio_count, pipes, signal_pipe[1], pid); + + /* Release lock in parent process */ + uv_rwlock_wrunlock(&loop->cloexec_lock); + + uv__close(signal_pipe[1]); + + if (err == 0) { + do + r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno)); + while (r == -1 && errno == EINTR); + + if (r == 0) + ; /* okay, EOF */ + else if (r == sizeof(exec_errorno)) { + do + err = waitpid(*pid, &status, 0); /* okay, read errorno */ + while (err == -1 && errno == EINTR); + assert(err == *pid); + err = exec_errorno; + } else if (r == -1 && errno == EPIPE) { + /* Something unknown happened to our child before spawn */ + do + err = waitpid(*pid, &status, 0); /* okay, got EPIPE */ + while (err == -1 && errno == EINTR); + assert(err == *pid); + err = UV_EPIPE; + } else + abort(); + } + + uv__close_nocheckstdio(signal_pipe[0]); + + return err; +} + int uv_spawn(uv_loop_t* loop, uv_process_t* process, const uv_process_options_t* options) { @@ -389,18 +980,13 @@ int uv_spawn(uv_loop_t* loop, /* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */ return UV_ENOSYS; #else - sigset_t signewset; - sigset_t sigoldset; - int signal_pipe[2] = { -1, -1 }; int pipes_storage[8][2]; int (*pipes)[2]; int stdio_count; - ssize_t r; pid_t pid; int err; int exec_errorno; int i; - int status; if (options->cpumask != NULL) { #ifndef CMAKE_BOOTSTRAP @@ -427,6 +1013,7 @@ int uv_spawn(uv_loop_t* loop, uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); QUEUE_INIT(&process->queue); + process->status = 0; stdio_count = options->stdio_count; if (stdio_count < 3) @@ -451,92 +1038,43 @@ int uv_spawn(uv_loop_t* loop, goto error; } - /* This pipe is used by the parent to wait until - * the child has called `execve()`. We need this - * to avoid the following race condition: - * - * if ((pid = fork()) > 0) { - * kill(pid, SIGTERM); - * } - * else if (pid == 0) { - * execve("/bin/cat", argp, envp); - * } - * - * The parent sends a signal immediately after forking. - * Since the child may not have called `execve()` yet, - * there is no telling what process receives the signal, - * our fork or /bin/cat. - * - * To avoid ambiguity, we create a pipe with both ends - * marked close-on-exec. Then, after the call to `fork()`, - * the parent polls the read end until it EOFs or errors with EPIPE. - */ - err = uv__make_pipe(signal_pipe, 0); - if (err) - goto error; - +#ifdef UV_USE_SIGCHLD uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD); +#endif - /* Acquire write lock to prevent opening new fds in worker threads */ - uv_rwlock_wrlock(&loop->cloexec_lock); - - /* Start the child with most signals blocked, to avoid any issues before we - * can reset them, but allow program failures to exit (and not hang). */ - sigfillset(&signewset); - sigdelset(&signewset, SIGKILL); - sigdelset(&signewset, SIGSTOP); - sigdelset(&signewset, SIGTRAP); - sigdelset(&signewset, SIGSEGV); - sigdelset(&signewset, SIGBUS); - sigdelset(&signewset, SIGILL); - sigdelset(&signewset, SIGSYS); - sigdelset(&signewset, SIGABRT); - if (pthread_sigmask(SIG_BLOCK, &signewset, &sigoldset) != 0) - abort(); - - pid = fork(); - if (pid == -1) - err = UV__ERR(errno); - - if (pid == 0) - uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]); - - if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0) - abort(); + /* Spawn the child */ + exec_errorno = uv__spawn_and_init_child(loop, options, stdio_count, pipes, &pid); - /* Release lock in parent process */ - uv_rwlock_wrunlock(&loop->cloexec_lock); +#if 0 + /* This runs into a nodejs issue (it expects initialized streams, even if the + * exec failed). + * See https://github.com/libuv/libuv/pull/3107#issuecomment-782482608 */ + if (exec_errorno != 0) + goto error; +#endif - uv__close(signal_pipe[1]); + /* Activate this handle if exec() happened successfully, even if we later + * fail to open a stdio handle. This ensures we can eventually reap the child + * with waitpid. */ + if (exec_errorno == 0) { +#ifndef UV_USE_SIGCHLD + struct kevent event; + EV_SET(&event, pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, 0); + if (kevent(loop->backend_fd, &event, 1, NULL, 0, NULL)) { + if (errno != ESRCH) + abort(); + /* Process already exited. Call waitpid on the next loop iteration. */ + process->flags |= UV_HANDLE_REAP; + loop->flags |= UV_LOOP_REAP_CHILDREN; + } +#endif - if (pid == -1) { - uv__close(signal_pipe[0]); - goto error; + process->pid = pid; + process->exit_cb = options->exit_cb; + QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue); + uv__handle_start(process); } - process->status = 0; - exec_errorno = 0; - do - r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno)); - while (r == -1 && errno == EINTR); - - if (r == 0) - ; /* okay, EOF */ - else if (r == sizeof(exec_errorno)) { - do - err = waitpid(pid, &status, 0); /* okay, read errorno */ - while (err == -1 && errno == EINTR); - assert(err == pid); - } else if (r == -1 && errno == EPIPE) { - do - err = waitpid(pid, &status, 0); /* okay, got EPIPE */ - while (err == -1 && errno == EINTR); - assert(err == pid); - } else - abort(); - - uv__close_nocheckstdio(signal_pipe[0]); - for (i = 0; i < options->stdio_count; i++) { err = uv__process_open_stream(options->stdio + i, pipes[i]); if (err == 0) @@ -548,15 +1086,6 @@ int uv_spawn(uv_loop_t* loop, goto error; } - /* Only activate this handle if exec() happened successfully */ - if (exec_errorno == 0) { - QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue); - uv__handle_start(process); - } - - process->pid = pid; - process->exit_cb = options->exit_cb; - if (pipes != pipes_storage) uv__free(pipes); @@ -589,9 +1118,16 @@ int uv_process_kill(uv_process_t* process, int signum) { int uv_kill(int pid, int signum) { - if (kill(pid, signum)) + if (kill(pid, signum)) { +#if defined(__MVS__) + /* EPERM is returned if the process is a zombie. */ + siginfo_t infop; + if (errno == EPERM && + waitid(P_PID, pid, &infop, WNOHANG | WNOWAIT | WEXITED) == 0) + return 0; +#endif return UV__ERR(errno); - else + } else return 0; } diff --git a/Utilities/cmlibuv/src/unix/stream.c b/Utilities/cmlibuv/src/unix/stream.c index 52e2b9a..1ce7525 100644 --- a/Utilities/cmlibuv/src/unix/stream.c +++ b/Utilities/cmlibuv/src/unix/stream.c @@ -66,6 +66,7 @@ static void uv__read(uv_stream_t* stream); static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events); static void uv__write_callbacks(uv_stream_t* stream); static size_t uv__write_req_size(uv_write_t* req); +static void uv__drain(uv_stream_t* stream); void uv__stream_init(uv_loop_t* loop, @@ -453,17 +454,7 @@ void uv__stream_destroy(uv_stream_t* stream) { uv__stream_flush_write_queue(stream, UV_ECANCELED); uv__write_callbacks(stream); - - if (stream->shutdown_req) { - /* The ECANCELED error code is a lie, the shutdown(2) syscall is a - * fait accompli at this point. Maybe we should revisit this in v0.11. - * A possible reason for leaving it unchanged is that it informs the - * callee that the handle has been destroyed. - */ - uv__req_unregister(stream->loop, stream->shutdown_req); - stream->shutdown_req->cb(stream->shutdown_req, UV_ECANCELED); - stream->shutdown_req = NULL; - } + uv__drain(stream); assert(stream->write_queue_size == 0); } @@ -641,14 +632,16 @@ done: int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { int err; - + if (uv__is_closing(stream)) { + return UV_EINVAL; + } switch (stream->type) { case UV_TCP: - err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb); + err = uv__tcp_listen((uv_tcp_t*)stream, backlog, cb); break; case UV_NAMED_PIPE: - err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb); + err = uv__pipe_listen((uv_pipe_t*)stream, backlog, cb); break; default: @@ -667,25 +660,30 @@ static void uv__drain(uv_stream_t* stream) { int err; assert(QUEUE_EMPTY(&stream->write_queue)); - uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); - uv__stream_osx_interrupt_select(stream); + if (!(stream->flags & UV_HANDLE_CLOSING)) { + uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); + uv__stream_osx_interrupt_select(stream); + } - /* Shutdown? */ - if ((stream->flags & UV_HANDLE_SHUTTING) && - !(stream->flags & UV_HANDLE_CLOSING) && - !(stream->flags & UV_HANDLE_SHUT)) { - assert(stream->shutdown_req); + if (!(stream->flags & UV_HANDLE_SHUTTING)) + return; - req = stream->shutdown_req; + req = stream->shutdown_req; + assert(req); + + if ((stream->flags & UV_HANDLE_CLOSING) || + !(stream->flags & UV_HANDLE_SHUT)) { stream->shutdown_req = NULL; stream->flags &= ~UV_HANDLE_SHUTTING; uv__req_unregister(stream->loop, req); err = 0; - if (shutdown(uv__stream_fd(stream), SHUT_WR)) + if (stream->flags & UV_HANDLE_CLOSING) + /* The user destroyed the stream before we got to do the shutdown. */ + err = UV_ECANCELED; + else if (shutdown(uv__stream_fd(stream), SHUT_WR)) err = UV__ERR(errno); - - if (err == 0) + else /* Success. */ stream->flags |= UV_HANDLE_SHUT; if (req->cb != NULL) @@ -926,7 +924,6 @@ static void uv__write(uv_stream_t* stream) { } req->error = n; - /* XXX(jwn): this must call uv__stream_flush_write_queue(stream, n) here, since we won't generate any more events */ uv__write_req_finish(req); uv__io_stop(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); @@ -964,49 +961,6 @@ static void uv__write_callbacks(uv_stream_t* stream) { } -uv_handle_type uv__handle_type(int fd) { - struct sockaddr_storage ss; - socklen_t sslen; - socklen_t len; - int type; - - memset(&ss, 0, sizeof(ss)); - sslen = sizeof(ss); - - if (getsockname(fd, (struct sockaddr*)&ss, &sslen)) - return UV_UNKNOWN_HANDLE; - - len = sizeof type; - - if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len)) - return UV_UNKNOWN_HANDLE; - - if (type == SOCK_STREAM) { -#if defined(_AIX) || defined(__DragonFly__) - /* on AIX/DragonFly the getsockname call returns an empty sa structure - * for sockets of type AF_UNIX. For all other types it will - * return a properly filled in structure. - */ - if (sslen == 0) - return UV_NAMED_PIPE; -#endif - switch (ss.ss_family) { - case AF_UNIX: - return UV_NAMED_PIPE; - case AF_INET: - case AF_INET6: - return UV_TCP; - } - } - - if (type == SOCK_DGRAM && - (ss.ss_family == AF_INET || ss.ss_family == AF_INET6)) - return UV_UDP; - - return UV_UNKNOWN_HANDLE; -} - - static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { stream->flags |= UV_HANDLE_READ_EOF; stream->flags &= ~UV_HANDLE_READING; @@ -1278,7 +1232,8 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { assert(uv__stream_fd(stream) >= 0); - /* Initialize request */ + /* Initialize request. The `shutdown(2)` call will always be deferred until + * `uv__drain`, just before the callback is run. */ uv__req_init(stream->loop, req, UV_SHUTDOWN); req->handle = stream; req->cb = cb; @@ -1286,8 +1241,8 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { stream->flags |= UV_HANDLE_SHUTTING; stream->flags &= ~UV_HANDLE_WRITABLE; - uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); - uv__stream_osx_interrupt_select(stream); + if (QUEUE_EMPTY(&stream->write_queue)) + uv__io_feed(stream->loop, &stream->io_watcher); return 0; } diff --git a/Utilities/cmlibuv/src/unix/sunos.c b/Utilities/cmlibuv/src/unix/sunos.c index eab2e40..85e4d60 100644 --- a/Utilities/cmlibuv/src/unix/sunos.c +++ b/Utilities/cmlibuv/src/unix/sunos.c @@ -158,7 +158,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { sigset_t set; uint64_t base; uint64_t diff; - uint64_t idle_poll; unsigned int nfds; unsigned int i; int saved_errno; @@ -428,7 +427,7 @@ void uv_loadavg(double avg[3]) { #if defined(PORT_SOURCE_FILE) static int uv__fs_event_rearm(uv_fs_event_t *handle) { - if (handle->fd == -1) + if (handle->fd == PORT_DELETED) return UV_EBADF; if (port_associate(handle->loop->fs_fd, @@ -479,6 +478,12 @@ static void uv__fs_event_read(uv_loop_t* loop, handle = (uv_fs_event_t*) pe.portev_user; assert((r == 0) && "unexpected port_get() error"); + if (uv__is_closing(handle)) { + uv__handle_stop(handle); + uv__make_close_pending((uv_handle_t*) handle); + break; + } + events = 0; if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED)) events |= UV_CHANGE; @@ -546,12 +551,14 @@ int uv_fs_event_start(uv_fs_event_t* handle, } -int uv_fs_event_stop(uv_fs_event_t* handle) { +static int uv__fs_event_stop(uv_fs_event_t* handle) { + int ret = 0; + if (!uv__is_active(handle)) return 0; - if (handle->fd == PORT_FIRED || handle->fd == PORT_LOADED) { - port_dissociate(handle->loop->fs_fd, + if (handle->fd == PORT_LOADED) { + ret = port_dissociate(handle->loop->fs_fd, PORT_SOURCE_FILE, (uintptr_t) &handle->fo); } @@ -560,13 +567,28 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { uv__free(handle->path); handle->path = NULL; handle->fo.fo_name = NULL; - uv__handle_stop(handle); + if (ret == 0) + uv__handle_stop(handle); + + return ret; +} +int uv_fs_event_stop(uv_fs_event_t* handle) { + (void) uv__fs_event_stop(handle); return 0; } void uv__fs_event_close(uv_fs_event_t* handle) { - uv_fs_event_stop(handle); + /* + * If we were unable to dissociate the port here, then it is most likely + * that there is a pending queued event. When this happens, we don't want + * to complete the close as it will free the underlying memory for the + * handle, causing a use-after-free problem when the event is processed. + * We defer the final cleanup until after the event is consumed in + * uv__fs_event_read(). + */ + if (uv__fs_event_stop(handle) == 0) + uv__make_close_pending((uv_handle_t*) handle); } #else /* !defined(PORT_SOURCE_FILE) */ diff --git a/Utilities/cmlibuv/src/unix/tcp.c b/Utilities/cmlibuv/src/unix/tcp.c index bc0fb66..73fc657 100644 --- a/Utilities/cmlibuv/src/unix/tcp.c +++ b/Utilities/cmlibuv/src/unix/tcp.c @@ -184,14 +184,15 @@ int uv__tcp_bind(uv_tcp_t* tcp, #endif errno = 0; - if (bind(tcp->io_watcher.fd, addr, addrlen) && errno != EADDRINUSE) { + err = bind(tcp->io_watcher.fd, addr, addrlen); + if (err == -1 && errno != EADDRINUSE) { if (errno == EAFNOSUPPORT) /* OSX, other BSDs and SunoS fail with EAFNOSUPPORT when binding a * socket created with AF_INET to an AF_INET6 address or vice versa. */ return UV_EINVAL; return UV__ERR(errno); } - tcp->delayed_error = UV__ERR(errno); + tcp->delayed_error = (err == -1) ? UV__ERR(errno) : 0; tcp->flags |= UV_HANDLE_BOUND; if (addr->sa_family == AF_INET6) @@ -320,15 +321,23 @@ int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) { return UV_EINVAL; fd = uv__stream_fd(handle); - if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) - return UV__ERR(errno); + if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l))) { + if (errno == EINVAL) { + /* Open Group Specifications Issue 7, 2018 edition states that + * EINVAL may mean the socket has been shut down already. + * Behavior observed on Solaris, illumos and macOS. */ + errno = 0; + } else { + return UV__ERR(errno); + } + } uv_close((uv_handle_t*) handle, close_cb); return 0; } -int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { +int uv__tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { static int single_accept_cached = -1; unsigned long flags; int single_accept; diff --git a/Utilities/cmlibuv/src/unix/thread.c b/Utilities/cmlibuv/src/unix/thread.c index cbddf17..5a07b02 100644 --- a/Utilities/cmlibuv/src/unix/thread.c +++ b/Utilities/cmlibuv/src/unix/thread.c @@ -162,12 +162,46 @@ void uv_barrier_destroy(uv_barrier_t* barrier) { #endif -/* On MacOS, threads other than the main thread are created with a reduced - * stack size by default. Adjust to RLIMIT_STACK aligned to the page size. +/* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is + * too small to safely receive signals on. + * + * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has + * the largest MINSIGSTKSZ of the architectures that musl supports) so + * let's use that as a lower bound. * - * On Linux, threads created by musl have a much smaller stack than threads + * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ + * is between 28 and 133 KB when compiling against glibc, depending + * on the architecture. + */ +static size_t uv__min_stack_size(void) { + static const size_t min = 8192; + +#ifdef PTHREAD_STACK_MIN /* Not defined on NetBSD. */ + if (min < (size_t) PTHREAD_STACK_MIN) + return PTHREAD_STACK_MIN; +#endif /* PTHREAD_STACK_MIN */ + + return min; +} + + +/* On Linux, threads created by musl have a much smaller stack than threads * created by glibc (80 vs. 2048 or 4096 kB.) Follow glibc for consistency. */ +static size_t uv__default_stack_size(void) { +#if !defined(__linux__) + return 0; +#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__) + return 4 << 20; /* glibc default. */ +#else + return 2 << 20; /* glibc default. */ +#endif +} + + +/* On MacOS, threads other than the main thread are created with a reduced + * stack size by default. Adjust to RLIMIT_STACK aligned to the page size. + */ size_t uv__thread_stack_size(void) { #if defined(__APPLE__) || defined(__linux__) struct rlimit lim; @@ -176,34 +210,20 @@ size_t uv__thread_stack_size(void) { * the system call wrapper invokes the wrong system call. Don't treat * that as fatal, just use the default stack size instead. */ - if (0 == getrlimit(RLIMIT_STACK, &lim) && lim.rlim_cur != RLIM_INFINITY) { - /* pthread_attr_setstacksize() expects page-aligned values. */ - lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); - - /* Musl's PTHREAD_STACK_MIN is 2 KB on all architectures, which is - * too small to safely receive signals on. - * - * Musl's PTHREAD_STACK_MIN + MINSIGSTKSZ == 8192 on arm64 (which has - * the largest MINSIGSTKSZ of the architectures that musl supports) so - * let's use that as a lower bound. - * - * We use a hardcoded value because PTHREAD_STACK_MIN + MINSIGSTKSZ - * is between 28 and 133 KB when compiling against glibc, depending - * on the architecture. - */ - if (lim.rlim_cur >= 8192) - if (lim.rlim_cur >= PTHREAD_STACK_MIN) - return lim.rlim_cur; - } -#endif + if (getrlimit(RLIMIT_STACK, &lim)) + return uv__default_stack_size(); -#if !defined(__linux__) - return 0; -#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__) - return 4 << 20; /* glibc default. */ -#else - return 2 << 20; /* glibc default. */ + if (lim.rlim_cur == RLIM_INFINITY) + return uv__default_stack_size(); + + /* pthread_attr_setstacksize() expects page-aligned values. */ + lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); + + if (lim.rlim_cur >= (rlim_t) uv__min_stack_size()) + return lim.rlim_cur; #endif + + return uv__default_stack_size(); } @@ -222,6 +242,7 @@ int uv_thread_create_ex(uv_thread_t* tid, pthread_attr_t attr_storage; size_t pagesize; size_t stack_size; + size_t min_stack_size; /* Used to squelch a -Wcast-function-type warning. */ union { @@ -239,10 +260,9 @@ int uv_thread_create_ex(uv_thread_t* tid, pagesize = (size_t)getpagesize(); /* Round up to the nearest page boundary. */ stack_size = (stack_size + pagesize - 1) &~ (pagesize - 1); -#ifdef PTHREAD_STACK_MIN - if (stack_size < PTHREAD_STACK_MIN) - stack_size = PTHREAD_STACK_MIN; -#endif + min_stack_size = uv__min_stack_size(); + if (stack_size < min_stack_size) + stack_size = min_stack_size; } if (stack_size > 0) { diff --git a/Utilities/cmlibuv/src/unix/tty.c b/Utilities/cmlibuv/src/unix/tty.c index 8cefc15..44fdb9c 100644 --- a/Utilities/cmlibuv/src/unix/tty.c +++ b/Utilities/cmlibuv/src/unix/tty.c @@ -62,10 +62,25 @@ static int isreallyatty(int file) { #define isatty(fd) isreallyatty(fd) #endif +#if !defined(CMAKE_BOOTSTRAP) + static int orig_termios_fd = -1; static struct termios orig_termios; static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; +int uv__tcsetattr(int fd, int how, const struct termios *term) { + int rc; + + do + rc = tcsetattr(fd, how, term); + while (rc == -1 && errno == EINTR); + + if (rc == -1) + return UV__ERR(errno); + + return 0; +} + static int uv__tty_is_slave(const int fd) { int result; #if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) @@ -265,13 +280,18 @@ static void uv__tty_make_raw(struct termios* tio) { int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { struct termios tmp; int fd; + int rc; if (tty->mode == (int) mode) return 0; fd = uv__stream_fd(tty); if (tty->mode == UV_TTY_MODE_NORMAL && mode != UV_TTY_MODE_NORMAL) { - if (tcgetattr(fd, &tty->orig_termios)) + do + rc = tcgetattr(fd, &tty->orig_termios); + while (rc == -1 && errno == EINTR); + + if (rc == -1) return UV__ERR(errno); /* This is used for uv_tty_reset_mode() */ @@ -301,11 +321,11 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { } /* Apply changes after draining */ - if (tcsetattr(fd, TCSADRAIN, &tmp)) - return UV__ERR(errno); + rc = uv__tcsetattr(fd, TCSADRAIN, &tmp); + if (rc == 0) + tty->mode = mode; - tty->mode = mode; - return 0; + return rc; } @@ -326,9 +346,10 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { return 0; } +#endif uv_handle_type uv_guess_handle(uv_file file) { - struct sockaddr sa; + struct sockaddr_storage ss; struct stat s; socklen_t len; int type; @@ -339,8 +360,24 @@ uv_handle_type uv_guess_handle(uv_file file) { if (isatty(file)) return UV_TTY; - if (fstat(file, &s)) + if (fstat(file, &s)) { +#if defined(__PASE__) + /* On ibmi receiving RST from TCP instead of FIN immediately puts fd into + * an error state. fstat will return EINVAL, getsockname will also return + * EINVAL, even if sockaddr_storage is valid. (If file does not refer to a + * socket, ENOTSOCK is returned instead.) + * In such cases, we will permit the user to open the connection as uv_tcp + * still, so that the user can get immediately notified of the error in + * their read callback and close this fd. + */ + len = sizeof(ss); + if (getsockname(file, (struct sockaddr*) &ss, &len)) { + if (errno == EINVAL) + return UV_TCP; + } +#endif return UV_UNKNOWN_HANDLE; + } if (S_ISREG(s.st_mode)) return UV_FILE; @@ -354,16 +391,29 @@ uv_handle_type uv_guess_handle(uv_file file) { if (!S_ISSOCK(s.st_mode)) return UV_UNKNOWN_HANDLE; - len = sizeof(type); - if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len)) + len = sizeof(ss); + if (getsockname(file, (struct sockaddr*) &ss, &len)) { +#if defined(_AIX) + /* On aix receiving RST from TCP instead of FIN immediately puts fd into + * an error state. In such case getsockname will return EINVAL, even if + * sockaddr_storage is valid. + * In such cases, we will permit the user to open the connection as uv_tcp + * still, so that the user can get immediately notified of the error in + * their read callback and close this fd. + */ + if (errno == EINVAL) { + return UV_TCP; + } +#endif return UV_UNKNOWN_HANDLE; + } - len = sizeof(sa); - if (getsockname(file, &sa, &len)) + len = sizeof(type); + if (getsockopt(file, SOL_SOCKET, SO_TYPE, &type, &len)) return UV_UNKNOWN_HANDLE; if (type == SOCK_DGRAM) - if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) + if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) return UV_UDP; if (type == SOCK_STREAM) { @@ -376,15 +426,16 @@ uv_handle_type uv_guess_handle(uv_file file) { return UV_NAMED_PIPE; #endif /* defined(_AIX) || defined(__DragonFly__) */ - if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) + if (ss.ss_family == AF_INET || ss.ss_family == AF_INET6) return UV_TCP; - if (sa.sa_family == AF_UNIX) + if (ss.ss_family == AF_UNIX) return UV_NAMED_PIPE; } return UV_UNKNOWN_HANDLE; } +#if !defined(CMAKE_BOOTSTRAP) /* This function is async signal-safe, meaning that it's safe to call from * inside a signal handler _unless_ execution was inside uv_tty_set_mode()'s @@ -400,8 +451,7 @@ int uv_tty_reset_mode(void) { err = 0; if (orig_termios_fd != -1) - if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios)) - err = UV__ERR(errno); + err = uv__tcsetattr(orig_termios_fd, TCSANOW, &orig_termios); uv_spinlock_unlock(&termios_spinlock); errno = saved_errno; @@ -415,3 +465,5 @@ void uv_tty_set_vterm_state(uv_tty_vtermstate_t state) { int uv_tty_get_vterm_state(uv_tty_vtermstate_t* state) { return UV_ENOTSUP; } + +#endif diff --git a/Utilities/cmlibuv/src/unix/udp.c b/Utilities/cmlibuv/src/unix/udp.c index aee8d63..4d985b8 100644 --- a/Utilities/cmlibuv/src/unix/udp.c +++ b/Utilities/cmlibuv/src/unix/udp.c @@ -201,6 +201,7 @@ static int uv__udp_recvmmsg(uv_udp_t* handle, uv_buf_t* buf) { for (k = 0; k < chunks; ++k) { iov[k].iov_base = buf->base + k * UV__UDP_DGRAM_MAXSIZE; iov[k].iov_len = UV__UDP_DGRAM_MAXSIZE; + memset(&msgs[k].msg_hdr, 0, sizeof(msgs[k].msg_hdr)); msgs[k].msg_hdr.msg_iov = iov + k; msgs[k].msg_hdr.msg_iovlen = 1; msgs[k].msg_hdr.msg_name = peers + k; @@ -494,7 +495,7 @@ static int uv__set_reuse(int fd) { if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) return UV__ERR(errno); } -#elif defined(SO_REUSEPORT) && !defined(__linux__) +#elif defined(SO_REUSEPORT) && !defined(__linux__) && !defined(__GNU__) if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &yes, sizeof(yes))) return UV__ERR(errno); #else @@ -655,16 +656,16 @@ int uv__udp_connect(uv_udp_t* handle, } /* From https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html - * Any of uv supported UNIXs kernel should be standardized, but the kernel + * Any of uv supported UNIXs kernel should be standardized, but the kernel * implementation logic not same, let's use pseudocode to explain the udp * disconnect behaviors: - * + * * Predefined stubs for pseudocode: * 1. sodisconnect: The function to perform the real udp disconnect * 2. pru_connect: The function to perform the real udp connect * 3. so: The kernel object match with socket fd * 4. addr: The sockaddr parameter from user space - * + * * BSDs: * if(sodisconnect(so) == 0) { // udp disconnect succeed * if (addr->sa_len != so->addr->sa_len) return EINVAL; @@ -694,16 +695,25 @@ int uv__udp_disconnect(uv_udp_t* handle) { #endif memset(&addr, 0, sizeof(addr)); - + #if defined(__MVS__) addr.ss_family = AF_UNSPEC; #else addr.sa_family = AF_UNSPEC; #endif - + do { errno = 0; +#ifdef __PASE__ + /* On IBMi a connectionless transport socket can be disconnected by + * either setting the addr parameter to NULL or setting the + * addr_length parameter to zero, and issuing another connect(). + * https://www.ibm.com/docs/en/i/7.4?topic=ssw_ibm_i_74/apis/connec.htm + */ + r = connect(handle->io_watcher.fd, (struct sockaddr*) NULL, 0); +#else r = connect(handle->io_watcher.fd, (struct sockaddr*) &addr, sizeof(addr)); +#endif } while (r == -1 && errno == EINTR); if (r == -1) { @@ -927,7 +937,8 @@ static int uv__udp_set_membership6(uv_udp_t* handle, !defined(__NetBSD__) && \ !defined(__ANDROID__) && \ !defined(__DragonFly__) && \ - !defined(__QNX__) + !defined(__QNX__) && \ + !defined(__GNU__) static int uv__udp_set_source_membership4(uv_udp_t* handle, const struct sockaddr_in* multicast_addr, const char* interface_addr, @@ -1119,7 +1130,8 @@ int uv_udp_set_source_membership(uv_udp_t* handle, !defined(__NetBSD__) && \ !defined(__ANDROID__) && \ !defined(__DragonFly__) && \ - !defined(__QNX__) + !defined(__QNX__) && \ + !defined(__GNU__) int err; union uv__sockaddr mcast_addr; union uv__sockaddr src_addr; diff --git a/Utilities/cmlibuv/src/uv-common.c b/Utilities/cmlibuv/src/uv-common.c index e88347a..d8f7b0e 100644 --- a/Utilities/cmlibuv/src/uv-common.c +++ b/Utilities/cmlibuv/src/uv-common.c @@ -296,7 +296,9 @@ int uv_tcp_bind(uv_tcp_t* handle, if (handle->type != UV_TCP) return UV_EINVAL; - + if (uv__is_closing(handle)) { + return UV_EINVAL; + } if (addr->sa_family == AF_INET) addrlen = sizeof(struct sockaddr_in); else if (addr->sa_family == AF_INET6) diff --git a/Utilities/cmlibuv/src/uv-common.h b/Utilities/cmlibuv/src/uv-common.h index 8a190bf..6001b0c 100644 --- a/Utilities/cmlibuv/src/uv-common.h +++ b/Utilities/cmlibuv/src/uv-common.h @@ -130,7 +130,10 @@ enum { UV_SIGNAL_ONE_SHOT = 0x02000000, /* Only used by uv_poll_t handles. */ - UV_HANDLE_POLL_SLOW = 0x01000000 + UV_HANDLE_POLL_SLOW = 0x01000000, + + /* Only used by uv_process_t handles. */ + UV_HANDLE_REAP = 0x10000000 }; int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); diff --git a/Utilities/cmlibuv/src/win/async.c b/Utilities/cmlibuv/src/win/async.c index d787f66..b904676 100644 --- a/Utilities/cmlibuv/src/win/async.c +++ b/Utilities/cmlibuv/src/win/async.c @@ -28,7 +28,7 @@ #include "req-inl.h" -void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) { +void uv__async_endgame(uv_loop_t* loop, uv_async_t* handle) { if (handle->flags & UV_HANDLE_CLOSING && !handle->async_sent) { assert(!(handle->flags & UV_HANDLE_CLOSED)); @@ -54,9 +54,9 @@ int uv_async_init(uv_loop_t* loop, uv_async_t* handle, uv_async_cb async_cb) { } -void uv_async_close(uv_loop_t* loop, uv_async_t* handle) { +void uv__async_close(uv_loop_t* loop, uv_async_t* handle) { if (!((uv_async_t*)handle)->async_sent) { - uv_want_endgame(loop, (uv_handle_t*) handle); + uv__want_endgame(loop, (uv_handle_t*) handle); } uv__handle_closing(handle); @@ -83,7 +83,7 @@ int uv_async_send(uv_async_t* handle) { } -void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, +void uv__process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, uv_req_t* req) { assert(handle->type == UV_ASYNC); assert(req->type == UV_WAKEUP); @@ -91,7 +91,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, handle->async_sent = 0; if (handle->flags & UV_HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*)handle); + uv__want_endgame(loop, (uv_handle_t*)handle); } else if (handle->async_cb != NULL) { handle->async_cb(handle); } diff --git a/Utilities/cmlibuv/src/win/core.c b/Utilities/cmlibuv/src/win/core.c index e53a0f8..67af93e 100644 --- a/Utilities/cmlibuv/src/win/core.c +++ b/Utilities/cmlibuv/src/win/core.c @@ -84,10 +84,12 @@ static int uv__loops_capacity; #define UV__LOOPS_CHUNK_SIZE 8 static uv_mutex_t uv__loops_lock; + static void uv__loops_init(void) { uv_mutex_init(&uv__loops_lock); } + static int uv__loops_add(uv_loop_t* loop) { uv_loop_t** new_loops; int new_capacity, i; @@ -115,6 +117,7 @@ failed_loops_realloc: return ERROR_OUTOFMEMORY; } + static void uv__loops_remove(uv_loop_t* loop) { int loop_index; int smaller_capacity; @@ -173,7 +176,7 @@ void uv__wake_all_loops(void) { uv_mutex_unlock(&uv__loops_lock); } -static void uv_init(void) { +static void uv__init(void) { /* Tell Windows that we will handle critical errors. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); @@ -199,19 +202,19 @@ static void uv_init(void) { /* Fetch winapi function pointers. This must be done first because other * initialization code might need these function pointers to be loaded. */ - uv_winapi_init(); + uv__winapi_init(); /* Initialize winsock */ - uv_winsock_init(); + uv__winsock_init(); /* Initialize FS */ - uv_fs_init(); + uv__fs_init(); /* Initialize signal stuff */ - uv_signals_init(); + uv__signals_init(); /* Initialize console */ - uv_console_init(); + uv__console_init(); /* Initialize utilities */ uv__util_init(); @@ -327,7 +330,7 @@ void uv_update_time(uv_loop_t* loop) { void uv__once_init(void) { - uv_once(&uv_init_guard_, uv_init); + uv_once(&uv_init_guard_, uv__init); } @@ -395,23 +398,28 @@ int uv_loop_fork(uv_loop_t* loop) { } -int uv_backend_timeout(const uv_loop_t* loop) { - if (loop->stop_flag != 0) - return 0; - - if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop)) - return 0; +static int uv__loop_alive(const uv_loop_t* loop) { + return uv__has_active_handles(loop) || + uv__has_active_reqs(loop) || + loop->pending_reqs_tail != NULL || + loop->endgame_handles != NULL; +} - if (loop->pending_reqs_tail) - return 0; - if (loop->endgame_handles) - return 0; +int uv_loop_alive(const uv_loop_t* loop) { + return uv__loop_alive(loop); +} - if (loop->idle_handles) - return 0; - return uv__next_timeout(loop); +int uv_backend_timeout(const uv_loop_t* loop) { + if (loop->stop_flag == 0 && + /* uv__loop_alive(loop) && */ + (uv__has_active_handles(loop) || uv__has_active_reqs(loop)) && + loop->pending_reqs_tail == NULL && + loop->idle_handles == NULL && + loop->endgame_handles == NULL) + return uv__next_timeout(loop); + return 0; } @@ -462,8 +470,8 @@ static void uv__poll_wine(uv_loop_t* loop, DWORD timeout) { if (overlapped) { /* Package was dequeued */ - req = uv_overlapped_to_req(overlapped); - uv_insert_pending_req(loop, req); + req = uv__overlapped_to_req(overlapped); + uv__insert_pending_req(loop, req); /* Some time might have passed waiting for I/O, * so update the loop time here. @@ -547,8 +555,8 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) { * meant only to wake us up. */ if (overlappeds[i].lpOverlapped) { - req = uv_overlapped_to_req(overlappeds[i].lpOverlapped); - uv_insert_pending_req(loop, req); + req = uv__overlapped_to_req(overlappeds[i].lpOverlapped); + uv__insert_pending_req(loop, req); } } @@ -581,22 +589,10 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) { } -static int uv__loop_alive(const uv_loop_t* loop) { - return uv__has_active_handles(loop) || - uv__has_active_reqs(loop) || - loop->endgame_handles != NULL; -} - - -int uv_loop_alive(const uv_loop_t* loop) { - return uv__loop_alive(loop); -} - - int uv_run(uv_loop_t *loop, uv_run_mode mode) { DWORD timeout; int r; - int ran_pending; + int can_sleep; r = uv__loop_alive(loop); if (!r) @@ -606,12 +602,14 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { uv_update_time(loop); uv__run_timers(loop); - ran_pending = uv_process_reqs(loop); - uv_idle_invoke(loop); - uv_prepare_invoke(loop); + can_sleep = loop->pending_reqs_tail == NULL && loop->idle_handles == NULL; + + uv__process_reqs(loop); + uv__idle_invoke(loop); + uv__prepare_invoke(loop); timeout = 0; - if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) + if ((mode == UV_RUN_ONCE && can_sleep) || mode == UV_RUN_DEFAULT) timeout = uv_backend_timeout(loop); if (pGetQueuedCompletionStatusEx) @@ -619,6 +617,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { else uv__poll_wine(loop, timeout); + /* Process immediate callbacks (e.g. write_cb) a small fixed number of + * times to avoid loop starvation.*/ + for (r = 0; r < 8 && loop->pending_reqs_tail != NULL; r++) + uv__process_reqs(loop); + /* Run one final update on the provider_idle_time in case uv__poll* * returned because the timeout expired, but no events were received. This * call will be ignored if the provider_entry_time was either never set (if @@ -626,8 +629,8 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { */ uv__metrics_update_idle_time(loop); - uv_check_invoke(loop); - uv_process_endgames(loop); + uv__check_invoke(loop); + uv__process_endgames(loop); if (mode == UV_RUN_ONCE) { /* UV_RUN_ONCE implies forward progress: at least one callback must have @@ -638,6 +641,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from * the check. */ + uv_update_time(loop); uv__run_timers(loop); } diff --git a/Utilities/cmlibuv/src/win/fs-event.c b/Utilities/cmlibuv/src/win/fs-event.c index 76da077..6758c7c 100644 --- a/Utilities/cmlibuv/src/win/fs-event.c +++ b/Utilities/cmlibuv/src/win/fs-event.c @@ -33,7 +33,7 @@ const unsigned int uv_directory_watcher_buffer_size = 4096; -static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop, +static void uv__fs_event_queue_readdirchanges(uv_loop_t* loop, uv_fs_event_t* handle) { assert(handle->dir_handle != INVALID_HANDLE_VALUE); assert(!handle->req_pending); @@ -57,15 +57,15 @@ static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop, NULL)) { /* Make this req pending reporting an error. */ SET_REQ_ERROR(&handle->req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)&handle->req); + uv__insert_pending_req(loop, (uv_req_t*)&handle->req); } handle->req_pending = 1; } -static void uv_relative_path(const WCHAR* filename, - const WCHAR* dir, - WCHAR** relpath) { +static void uv__relative_path(const WCHAR* filename, + const WCHAR* dir, + WCHAR** relpath) { size_t relpathlen; size_t filenamelen = wcslen(filename); size_t dirlen = wcslen(dir); @@ -80,7 +80,7 @@ static void uv_relative_path(const WCHAR* filename, (*relpath)[relpathlen] = L'\0'; } -static int uv_split_path(const WCHAR* filename, WCHAR** dir, +static int uv__split_path(const WCHAR* filename, WCHAR** dir, WCHAR** file) { size_t len, i; DWORD dir_len; @@ -255,12 +255,12 @@ int uv_fs_event_start(uv_fs_event_t* handle, short_path_done: short_path = short_path_buffer; - if (uv_split_path(pathw, &dir, &handle->filew) != 0) { + if (uv__split_path(pathw, &dir, &handle->filew) != 0) { last_error = GetLastError(); goto error; } - if (uv_split_path(short_path, NULL, &handle->short_filew) != 0) { + if (uv__split_path(short_path, NULL, &handle->short_filew) != 0) { last_error = GetLastError(); goto error; } @@ -423,7 +423,7 @@ static int file_info_cmp(WCHAR* str, WCHAR* file_name, size_t file_name_len) { } -void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, +void uv__process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle) { FILE_NOTIFY_INFORMATION* file_info; int err, sizew, size; @@ -442,7 +442,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, */ if (!uv__is_active(handle)) { if (handle->flags & UV_HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*) handle); + uv__want_endgame(loop, (uv_handle_t*) handle); } return; } @@ -515,9 +515,9 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, if (long_filenamew) { /* Get the file name out of the long path. */ - uv_relative_path(long_filenamew, - handle->dirw, - &filenamew); + uv__relative_path(long_filenamew, + handle->dirw, + &filenamew); uv__free(long_filenamew); long_filenamew = filenamew; sizew = -1; @@ -575,26 +575,26 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, } if (handle->flags & UV_HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*)handle); + uv__want_endgame(loop, (uv_handle_t*)handle); } else if (uv__is_active(handle)) { - uv_fs_event_queue_readdirchanges(loop, handle); + uv__fs_event_queue_readdirchanges(loop, handle); } } -void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) { +void uv__fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) { uv_fs_event_stop(handle); uv__handle_closing(handle); if (!handle->req_pending) { - uv_want_endgame(loop, (uv_handle_t*)handle); + uv__want_endgame(loop, (uv_handle_t*)handle); } } -void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) { +void uv__fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) { if ((handle->flags & UV_HANDLE_CLOSING) && !handle->req_pending) { assert(!(handle->flags & UV_HANDLE_CLOSED)); diff --git a/Utilities/cmlibuv/src/win/fs.c b/Utilities/cmlibuv/src/win/fs.c index 9037641..7923079 100644 --- a/Utilities/cmlibuv/src/win/fs.c +++ b/Utilities/cmlibuv/src/win/fs.c @@ -46,7 +46,7 @@ do { \ if (req == NULL) \ return UV_EINVAL; \ - uv_fs_req_init(loop, req, subtype, cb); \ + uv__fs_req_init(loop, req, subtype, cb); \ } \ while (0) @@ -132,7 +132,7 @@ static int uv__file_symlink_usermode_flag = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGE static DWORD uv__allocation_granularity; -void uv_fs_init(void) { +void uv__fs_init(void) { SYSTEM_INFO system_info; GetSystemInfo(&system_info); @@ -241,7 +241,7 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, -INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, +INLINE static void uv__fs_req_init(uv_loop_t* loop, uv_fs_t* req, uv_fs_type fs_type, const uv_fs_cb cb) { uv__once_init(); UV_REQ_INIT(req, UV_FS); @@ -912,12 +912,11 @@ void fs__read(uv_fs_t* req) { SET_REQ_RESULT(req, bytes); } else { error = GetLastError(); - if (error == ERROR_ACCESS_DENIED) { error = ERROR_INVALID_FLAGS; } - if (error == ERROR_HANDLE_EOF) { + if (error == ERROR_HANDLE_EOF || error == ERROR_BROKEN_PIPE) { SET_REQ_RESULT(req, bytes); } else { SET_REQ_WIN32_ERROR(req, error); @@ -1881,8 +1880,9 @@ INLINE static DWORD fs__stat_impl_from_path(WCHAR* path, NULL); if (handle == INVALID_HANDLE_VALUE) - ret = GetLastError(); - else if (fs__stat_handle(handle, statbuf, do_lstat) != 0) + return GetLastError(); + + if (fs__stat_handle(handle, statbuf, do_lstat) != 0) ret = GetLastError(); else ret = 0; @@ -2300,13 +2300,13 @@ INLINE static DWORD fs__utime_impl_from_path(WCHAR* path, flags, NULL); - if (handle == INVALID_HANDLE_VALUE) { - ret = GetLastError(); - } else if (fs__utime_handle(handle, atime, mtime) != 0) { + if (handle == INVALID_HANDLE_VALUE) + return GetLastError(); + + if (fs__utime_handle(handle, atime, mtime) != 0) ret = GetLastError(); - } else { + else ret = 0; - } CloseHandle(handle); return ret; diff --git a/Utilities/cmlibuv/src/win/handle-inl.h b/Utilities/cmlibuv/src/win/handle-inl.h index 82c657d..5c843c2 100644 --- a/Utilities/cmlibuv/src/win/handle-inl.h +++ b/Utilities/cmlibuv/src/win/handle-inl.h @@ -55,7 +55,7 @@ \ if (handle->flags & UV_HANDLE_CLOSING && \ handle->reqs_pending == 0) { \ - uv_want_endgame(loop, (uv_handle_t*)handle); \ + uv__want_endgame(loop, (uv_handle_t*)handle); \ } \ } while (0) @@ -85,7 +85,7 @@ } while (0) -INLINE static void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) { +INLINE static void uv__want_endgame(uv_loop_t* loop, uv_handle_t* handle) { if (!(handle->flags & UV_HANDLE_ENDGAME_QUEUED)) { handle->flags |= UV_HANDLE_ENDGAME_QUEUED; @@ -95,7 +95,7 @@ INLINE static void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle) { } -INLINE static void uv_process_endgames(uv_loop_t* loop) { +INLINE static void uv__process_endgames(uv_loop_t* loop) { uv_handle_t* handle; while (loop->endgame_handles) { @@ -106,23 +106,23 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) { switch (handle->type) { case UV_TCP: - uv_tcp_endgame(loop, (uv_tcp_t*) handle); + uv__tcp_endgame(loop, (uv_tcp_t*) handle); break; case UV_NAMED_PIPE: - uv_pipe_endgame(loop, (uv_pipe_t*) handle); + uv__pipe_endgame(loop, (uv_pipe_t*) handle); break; case UV_TTY: - uv_tty_endgame(loop, (uv_tty_t*) handle); + uv__tty_endgame(loop, (uv_tty_t*) handle); break; case UV_UDP: - uv_udp_endgame(loop, (uv_udp_t*) handle); + uv__udp_endgame(loop, (uv_udp_t*) handle); break; case UV_POLL: - uv_poll_endgame(loop, (uv_poll_t*) handle); + uv__poll_endgame(loop, (uv_poll_t*) handle); break; case UV_TIMER: @@ -133,23 +133,23 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) { case UV_PREPARE: case UV_CHECK: case UV_IDLE: - uv_loop_watcher_endgame(loop, handle); + uv__loop_watcher_endgame(loop, handle); break; case UV_ASYNC: - uv_async_endgame(loop, (uv_async_t*) handle); + uv__async_endgame(loop, (uv_async_t*) handle); break; case UV_SIGNAL: - uv_signal_endgame(loop, (uv_signal_t*) handle); + uv__signal_endgame(loop, (uv_signal_t*) handle); break; case UV_PROCESS: - uv_process_endgame(loop, (uv_process_t*) handle); + uv__process_endgame(loop, (uv_process_t*) handle); break; case UV_FS_EVENT: - uv_fs_event_endgame(loop, (uv_fs_event_t*) handle); + uv__fs_event_endgame(loop, (uv_fs_event_t*) handle); break; case UV_FS_POLL: diff --git a/Utilities/cmlibuv/src/win/handle.c b/Utilities/cmlibuv/src/win/handle.c index 61e4df6..53a81fd 100644 --- a/Utilities/cmlibuv/src/win/handle.c +++ b/Utilities/cmlibuv/src/win/handle.c @@ -77,63 +77,63 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) { /* Handle-specific close actions */ switch (handle->type) { case UV_TCP: - uv_tcp_close(loop, (uv_tcp_t*)handle); + uv__tcp_close(loop, (uv_tcp_t*)handle); return; case UV_NAMED_PIPE: - uv_pipe_close(loop, (uv_pipe_t*) handle); + uv__pipe_close(loop, (uv_pipe_t*) handle); return; case UV_TTY: - uv_tty_close((uv_tty_t*) handle); + uv__tty_close((uv_tty_t*) handle); return; case UV_UDP: - uv_udp_close(loop, (uv_udp_t*) handle); + uv__udp_close(loop, (uv_udp_t*) handle); return; case UV_POLL: - uv_poll_close(loop, (uv_poll_t*) handle); + uv__poll_close(loop, (uv_poll_t*) handle); return; case UV_TIMER: uv_timer_stop((uv_timer_t*)handle); uv__handle_closing(handle); - uv_want_endgame(loop, handle); + uv__want_endgame(loop, handle); return; case UV_PREPARE: uv_prepare_stop((uv_prepare_t*)handle); uv__handle_closing(handle); - uv_want_endgame(loop, handle); + uv__want_endgame(loop, handle); return; case UV_CHECK: uv_check_stop((uv_check_t*)handle); uv__handle_closing(handle); - uv_want_endgame(loop, handle); + uv__want_endgame(loop, handle); return; case UV_IDLE: uv_idle_stop((uv_idle_t*)handle); uv__handle_closing(handle); - uv_want_endgame(loop, handle); + uv__want_endgame(loop, handle); return; case UV_ASYNC: - uv_async_close(loop, (uv_async_t*) handle); + uv__async_close(loop, (uv_async_t*) handle); return; case UV_SIGNAL: - uv_signal_close(loop, (uv_signal_t*) handle); + uv__signal_close(loop, (uv_signal_t*) handle); return; case UV_PROCESS: - uv_process_close(loop, (uv_process_t*) handle); + uv__process_close(loop, (uv_process_t*) handle); return; case UV_FS_EVENT: - uv_fs_event_close(loop, (uv_fs_event_t*) handle); + uv__fs_event_close(loop, (uv_fs_event_t*) handle); return; case UV_FS_POLL: diff --git a/Utilities/cmlibuv/src/win/internal.h b/Utilities/cmlibuv/src/win/internal.h index 7e1aef4..3e92a66 100644 --- a/Utilities/cmlibuv/src/win/internal.h +++ b/Utilities/cmlibuv/src/win/internal.h @@ -76,25 +76,28 @@ typedef struct { uint32_t delayed_error; } uv__ipc_socket_xfer_info_t; -int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb); -int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client); -int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, +int uv__tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb); +int uv__tcp_accept(uv_tcp_t* server, uv_tcp_t* client); +int uv__tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb); -int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle, +int uv__tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); int uv__tcp_try_write(uv_tcp_t* handle, const uv_buf_t bufs[], unsigned int nbufs); -void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req); -void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, +void uv__process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req); +void uv__process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, uv_write_t* req); -void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, +void uv__process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req); -void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, +void uv__process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, uv_connect_t* req); +void uv__process_tcp_shutdown_req(uv_loop_t* loop, + uv_tcp_t* stream, + uv_shutdown_t* req); -void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp); -void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle); +void uv__tcp_close(uv_loop_t* loop, uv_tcp_t* tcp); +void uv__tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle); int uv__tcp_xfer_export(uv_tcp_t* handle, int pid, @@ -108,12 +111,12 @@ int uv__tcp_xfer_import(uv_tcp_t* tcp, /* * UDP */ -void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req); -void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, +void uv__process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req); +void uv__process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, uv_udp_send_t* req); -void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle); -void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle); +void uv__udp_close(uv_loop_t* loop, uv_udp_t* handle); +void uv__udp_endgame(uv_loop_t* loop, uv_udp_t* handle); /* @@ -122,9 +125,9 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle); int uv__create_stdio_pipe_pair(uv_loop_t* loop, uv_pipe_t* parent_pipe, HANDLE* child_pipe_ptr, unsigned int flags); -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); -int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client); -int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, +int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); +int uv__pipe_accept(uv_pipe_t* server, uv_stream_t* client); +int uv__pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb); void uv__pipe_read_stop(uv_pipe_t* handle); int uv__pipe_write(uv_loop_t* loop, @@ -134,75 +137,77 @@ int uv__pipe_write(uv_loop_t* loop, size_t nbufs, uv_stream_t* send_handle, uv_write_cb cb); +void uv__pipe_shutdown(uv_loop_t* loop, uv_pipe_t* handle, uv_shutdown_t* req); -void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, +void uv__process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, uv_req_t* req); -void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, +void uv__process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, uv_write_t* req); -void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, +void uv__process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, uv_req_t* raw_req); -void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, +void uv__process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, uv_connect_t* req); -void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, +void uv__process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, uv_shutdown_t* req); -void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle); -void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle); -void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle); +void uv__pipe_close(uv_loop_t* loop, uv_pipe_t* handle); +void uv__pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle); /* * TTY */ -void uv_console_init(void); +void uv__console_init(void); -int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, +int uv__tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb); -int uv_tty_read_stop(uv_tty_t* handle); -int uv_tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle, +int uv__tty_read_stop(uv_tty_t* handle); +int uv__tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); int uv__tty_try_write(uv_tty_t* handle, const uv_buf_t bufs[], unsigned int nbufs); -void uv_tty_close(uv_tty_t* handle); +void uv__tty_close(uv_tty_t* handle); -void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, +void uv__process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* req); -void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, +void uv__process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, uv_write_t* req); /* - * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working + * uv__process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working * TODO: find a way to remove it */ -void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, +void uv__process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* raw_req); /* - * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working + * uv__process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working * TODO: find a way to remove it */ -void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, +void uv__process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, uv_connect_t* req); - -void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle); +void uv__process_tty_shutdown_req(uv_loop_t* loop, + uv_tty_t* stream, + uv_shutdown_t* req); +void uv__tty_endgame(uv_loop_t* loop, uv_tty_t* handle); /* * Poll watchers */ -void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, +void uv__process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req); -int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle); -void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle); +int uv__poll_close(uv_loop_t* loop, uv_poll_t* handle); +void uv__poll_endgame(uv_loop_t* loop, uv_poll_t* handle); /* * Loop watchers */ -void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle); +void uv__loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle); -void uv_prepare_invoke(uv_loop_t* loop); -void uv_check_invoke(uv_loop_t* loop); -void uv_idle_invoke(uv_loop_t* loop); +void uv__prepare_invoke(uv_loop_t* loop); +void uv__check_invoke(uv_loop_t* loop); +void uv__idle_invoke(uv_loop_t* loop); void uv__once_init(void); @@ -210,53 +215,47 @@ void uv__once_init(void); /* * Async watcher */ -void uv_async_close(uv_loop_t* loop, uv_async_t* handle); -void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle); +void uv__async_close(uv_loop_t* loop, uv_async_t* handle); +void uv__async_endgame(uv_loop_t* loop, uv_async_t* handle); -void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, +void uv__process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, uv_req_t* req); /* * Signal watcher */ -void uv_signals_init(void); +void uv__signals_init(void); int uv__signal_dispatch(int signum); -void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle); -void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle); +void uv__signal_close(uv_loop_t* loop, uv_signal_t* handle); +void uv__signal_endgame(uv_loop_t* loop, uv_signal_t* handle); -void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, +void uv__process_signal_req(uv_loop_t* loop, uv_signal_t* handle, uv_req_t* req); /* * Spawn */ -void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle); -void uv_process_close(uv_loop_t* loop, uv_process_t* handle); -void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle); - - -/* - * Error - */ -int uv_translate_sys_error(int sys_errno); +void uv__process_proc_exit(uv_loop_t* loop, uv_process_t* handle); +void uv__process_close(uv_loop_t* loop, uv_process_t* handle); +void uv__process_endgame(uv_loop_t* loop, uv_process_t* handle); /* * FS */ -void uv_fs_init(void); +void uv__fs_init(void); /* * FS Event */ -void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, +void uv__process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle); -void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle); -void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle); +void uv__fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle); +void uv__fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle); /* @@ -303,28 +302,28 @@ HANDLE uv__stdio_handle(BYTE* buffer, int fd); /* * Winapi and ntapi utility functions */ -void uv_winapi_init(void); +void uv__winapi_init(void); /* * Winsock utility functions */ -void uv_winsock_init(void); +void uv__winsock_init(void); -int uv_ntstatus_to_winsock_error(NTSTATUS status); +int uv__ntstatus_to_winsock_error(NTSTATUS status); -BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target); -BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target); +BOOL uv__get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target); +BOOL uv__get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target); -int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers, +int WSAAPI uv__wsarecv_workaround(SOCKET socket, WSABUF* buffers, DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); -int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, +int WSAAPI uv__wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr, int* addr_len, WSAOVERLAPPED *overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine); -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, +int WSAAPI uv__msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, AFD_POLL_INFO* info_out, OVERLAPPED* overlapped); /* Whether there are any non-IFS LSPs stacked on TCP */ diff --git a/Utilities/cmlibuv/src/win/loop-watcher.c b/Utilities/cmlibuv/src/win/loop-watcher.c index ad7fbea..fad9e8a 100644 --- a/Utilities/cmlibuv/src/win/loop-watcher.c +++ b/Utilities/cmlibuv/src/win/loop-watcher.c @@ -26,7 +26,7 @@ #include "handle-inl.h" -void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { +void uv__loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { if (handle->flags & UV_HANDLE_CLOSING) { assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->flags |= UV_HANDLE_CLOSED; @@ -104,7 +104,7 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { } \ \ \ - void uv_##name##_invoke(uv_loop_t* loop) { \ + void uv__##name##_invoke(uv_loop_t* loop) { \ uv_##name##_t* handle; \ \ (loop)->next_##name##_handle = (loop)->name##_handles; \ diff --git a/Utilities/cmlibuv/src/win/pipe.c b/Utilities/cmlibuv/src/win/pipe.c index 984b766..9984618 100644 --- a/Utilities/cmlibuv/src/win/pipe.c +++ b/Utilities/cmlibuv/src/win/pipe.c @@ -98,13 +98,13 @@ static void eof_timer_destroy(uv_pipe_t* pipe); static void eof_timer_close_cb(uv_handle_t* handle); -static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { +static void uv__unique_pipe_name(char* ptr, char* name, size_t size) { snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%lu", ptr, GetCurrentProcessId()); } int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { - uv_stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); + uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); handle->reqs_pending = 0; handle->handle = INVALID_HANDLE_VALUE; @@ -120,15 +120,11 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { } -static void uv_pipe_connection_init(uv_pipe_t* handle) { - uv_connection_init((uv_stream_t*) handle); +static void uv__pipe_connection_init(uv_pipe_t* handle) { + assert(!(handle->flags & UV_HANDLE_PIPESERVER)); + uv__connection_init((uv_stream_t*) handle); handle->read_req.data = handle; handle->pipe.conn.eof_timer = NULL; - assert(!(handle->flags & UV_HANDLE_PIPESERVER)); - if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - handle->pipe.conn.readfile_thread_handle = NULL; - InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock); - } } @@ -209,7 +205,7 @@ static int uv__pipe_server( int err; for (;;) { - uv_unique_pipe_name(random, name, nameSize); + uv__unique_pipe_name(random, name, nameSize); pipeHandle = CreateNamedPipeA(name, access | FILE_FLAG_FIRST_PIPE_INSTANCE, @@ -393,6 +389,8 @@ int uv__create_stdio_pipe_pair(uv_loop_t* loop, unsigned int client_flags; int err; + uv__pipe_connection_init(parent_pipe); + server_pipe = INVALID_HANDLE_VALUE; client_pipe = INVALID_HANDLE_VALUE; @@ -427,7 +425,6 @@ int uv__create_stdio_pipe_pair(uv_loop_t* loop, goto error; } - uv_pipe_connection_init(parent_pipe); parent_pipe->handle = server_pipe; *child_pipe_ptr = client_pipe; @@ -450,11 +447,11 @@ int uv__create_stdio_pipe_pair(uv_loop_t* loop, } -static int uv_set_pipe_handle(uv_loop_t* loop, - uv_pipe_t* handle, - HANDLE pipeHandle, - int fd, - DWORD duplex_flags) { +static int uv__set_pipe_handle(uv_loop_t* loop, + uv_pipe_t* handle, + HANDLE pipeHandle, + int fd, + DWORD duplex_flags) { NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_MODE_INFORMATION mode_info; @@ -462,7 +459,9 @@ static int uv_set_pipe_handle(uv_loop_t* loop, DWORD current_mode = 0; DWORD err = 0; - if (handle->flags & UV_HANDLE_PIPESERVER) + assert(handle->flags & UV_HANDLE_CONNECTION); + assert(!(handle->flags & UV_HANDLE_PIPESERVER)); + if (handle->flags & UV_HANDLE_CLOSING) return UV_EINVAL; if (handle->handle != INVALID_HANDLE_VALUE) return UV_EBUSY; @@ -478,18 +477,17 @@ static int uv_set_pipe_handle(uv_loop_t* loop, */ if (!GetNamedPipeHandleState(pipeHandle, ¤t_mode, NULL, NULL, NULL, NULL, 0)) { - return -1; + return uv_translate_sys_error(GetLastError()); } else if (current_mode & PIPE_NOWAIT) { - SetLastError(ERROR_ACCESS_DENIED); - return -1; + return UV_EACCES; } } else { /* If this returns ERROR_INVALID_PARAMETER we probably opened * something that is not a pipe. */ if (err == ERROR_INVALID_PARAMETER) { - SetLastError(WSAENOTSOCK); + return UV_ENOTSOCK; } - return -1; + return uv_translate_sys_error(err); } } @@ -500,13 +498,15 @@ static int uv_set_pipe_handle(uv_loop_t* loop, sizeof(mode_info), FileModeInformation); if (nt_status != STATUS_SUCCESS) { - return -1; + return uv_translate_sys_error(err); } if (mode_info.Mode & FILE_SYNCHRONOUS_IO_ALERT || mode_info.Mode & FILE_SYNCHRONOUS_IO_NONALERT) { /* Non-overlapped pipe. */ handle->flags |= UV_HANDLE_NON_OVERLAPPED_PIPE; + handle->pipe.conn.readfile_thread_handle = NULL; + InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock); } else { /* Overlapped pipe. Try to associate with IOCP. */ if (CreateIoCompletionPort(pipeHandle, @@ -578,135 +578,109 @@ static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) { } -void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { - int err; +void uv__pipe_shutdown(uv_loop_t* loop, uv_pipe_t* handle, uv_shutdown_t *req) { DWORD result; - uv_shutdown_t* req; NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_PIPE_LOCAL_INFORMATION pipe_info; - uv__ipc_xfer_queue_item_t* xfer_queue_item; - - if ((handle->flags & UV_HANDLE_CONNECTION) && - handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - req = handle->stream.conn.shutdown_req; - - /* Clear the shutdown_req field so we don't go here again. */ - handle->stream.conn.shutdown_req = NULL; - - if (handle->flags & UV_HANDLE_CLOSING) { - UNREGISTER_HANDLE_REQ(loop, handle, req); - - /* Already closing. Cancel the shutdown. */ - if (req->cb) { - req->cb(req, UV_ECANCELED); - } - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - /* Try to avoid flushing the pipe buffer in the thread pool. */ - nt_status = pNtQueryInformationFile(handle->handle, - &io_status, - &pipe_info, - sizeof pipe_info, - FilePipeLocalInformation); - - if (nt_status != STATUS_SUCCESS) { - /* Failure */ - UNREGISTER_HANDLE_REQ(loop, handle, req); - - handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */ - if (req->cb) { - err = pRtlNtStatusToDosError(nt_status); - req->cb(req, uv_translate_sys_error(err)); - } - - DECREASE_PENDING_REQ_COUNT(handle); - return; - } + assert(handle->flags & UV_HANDLE_CONNECTION); + assert(req != NULL); + assert(handle->stream.conn.write_reqs_pending == 0); + SET_REQ_SUCCESS(req); - if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) { - /* Short-circuit, no need to call FlushFileBuffers. */ - uv_insert_pending_req(loop, (uv_req_t*) req); - return; - } + if (handle->flags & UV_HANDLE_CLOSING) { + uv__insert_pending_req(loop, (uv_req_t*) req); + return; + } - /* Run FlushFileBuffers in the thread pool. */ - result = QueueUserWorkItem(pipe_shutdown_thread_proc, - req, - WT_EXECUTELONGFUNCTION); - if (result) { - return; + /* Try to avoid flushing the pipe buffer in the thread pool. */ + nt_status = pNtQueryInformationFile(handle->handle, + &io_status, + &pipe_info, + sizeof pipe_info, + FilePipeLocalInformation); - } else { - /* Failure. */ - UNREGISTER_HANDLE_REQ(loop, handle, req); + if (nt_status != STATUS_SUCCESS) { + SET_REQ_ERROR(req, pRtlNtStatusToDosError(nt_status)); + handle->flags |= UV_HANDLE_WRITABLE; /* Questionable. */ + uv__insert_pending_req(loop, (uv_req_t*) req); + return; + } - handle->flags |= UV_HANDLE_WRITABLE; /* Questionable */ - if (req->cb) { - err = GetLastError(); - req->cb(req, uv_translate_sys_error(err)); - } + if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) { + /* Short-circuit, no need to call FlushFileBuffers: + * all writes have been read. */ + uv__insert_pending_req(loop, (uv_req_t*) req); + return; + } - DECREASE_PENDING_REQ_COUNT(handle); - return; - } + /* Run FlushFileBuffers in the thread pool. */ + result = QueueUserWorkItem(pipe_shutdown_thread_proc, + req, + WT_EXECUTELONGFUNCTION); + if (!result) { + SET_REQ_ERROR(req, GetLastError()); + handle->flags |= UV_HANDLE_WRITABLE; /* Questionable. */ + uv__insert_pending_req(loop, (uv_req_t*) req); + return; } +} - if (handle->flags & UV_HANDLE_CLOSING && - handle->reqs_pending == 0) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - if (handle->flags & UV_HANDLE_CONNECTION) { - /* Free pending sockets */ - while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) { - QUEUE* q; - SOCKET socket; +void uv__pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { + uv__ipc_xfer_queue_item_t* xfer_queue_item; - q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue); - QUEUE_REMOVE(q); - xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member); + assert(handle->reqs_pending == 0); + assert(handle->flags & UV_HANDLE_CLOSING); + assert(!(handle->flags & UV_HANDLE_CLOSED)); - /* Materialize socket and close it */ - socket = WSASocketW(FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - &xfer_queue_item->xfer_info.socket_info, - 0, - WSA_FLAG_OVERLAPPED); - uv__free(xfer_queue_item); + if (handle->flags & UV_HANDLE_CONNECTION) { + /* Free pending sockets */ + while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) { + QUEUE* q; + SOCKET socket; + + q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue); + QUEUE_REMOVE(q); + xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member); + + /* Materialize socket and close it */ + socket = WSASocketW(FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + &xfer_queue_item->xfer_info.socket_info, + 0, + WSA_FLAG_OVERLAPPED); + uv__free(xfer_queue_item); + + if (socket != INVALID_SOCKET) + closesocket(socket); + } + handle->pipe.conn.ipc_xfer_queue_length = 0; - if (socket != INVALID_SOCKET) - closesocket(socket); + if (handle->flags & UV_HANDLE_EMULATE_IOCP) { + if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { + UnregisterWait(handle->read_req.wait_handle); + handle->read_req.wait_handle = INVALID_HANDLE_VALUE; } - handle->pipe.conn.ipc_xfer_queue_length = 0; - - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(handle->read_req.wait_handle); - handle->read_req.wait_handle = INVALID_HANDLE_VALUE; - } - if (handle->read_req.event_handle != NULL) { - CloseHandle(handle->read_req.event_handle); - handle->read_req.event_handle = NULL; - } + if (handle->read_req.event_handle != NULL) { + CloseHandle(handle->read_req.event_handle); + handle->read_req.event_handle = NULL; } - - if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) - DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock); } - if (handle->flags & UV_HANDLE_PIPESERVER) { - assert(handle->pipe.serv.accept_reqs); - uv__free(handle->pipe.serv.accept_reqs); - handle->pipe.serv.accept_reqs = NULL; - } + if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) + DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock); + } - uv__handle_close(handle); + if (handle->flags & UV_HANDLE_PIPESERVER) { + assert(handle->pipe.serv.accept_reqs); + uv__free(handle->pipe.serv.accept_reqs); + handle->pipe.serv.accept_reqs = NULL; } + + uv__handle_close(handle); } @@ -731,7 +705,9 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { if (!name) { return UV_EINVAL; } - + if (uv__is_closing(handle)) { + return UV_EINVAL; + } if (!(handle->flags & UV_HANDLE_PIPESERVER)) { handle->pipe.serv.pending_instances = default_pending_pipe_instances; } @@ -815,7 +791,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { assert(loop); /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait - * for the pipe to become available with WaitNamedPipe. */ + * up to 30 seconds for the pipe to become available with WaitNamedPipe. */ while (WaitNamedPipeW(handle->name, 30000)) { /* The pipe is now available, try to connect. */ pipeHandle = open_named_pipe(handle->name, &duplex_flags); @@ -825,9 +801,10 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { SwitchToThread(); } - if (pipeHandle != INVALID_HANDLE_VALUE && - !uv_set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags)) { + if (pipeHandle != INVALID_HANDLE_VALUE) { SET_REQ_SUCCESS(req); + req->u.connect.pipeHandle = pipeHandle; + req->u.connect.duplex_flags = duplex_flags; } else { SET_REQ_ERROR(req, GetLastError()); } @@ -849,6 +826,18 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, UV_REQ_INIT(req, UV_CONNECT); req->handle = (uv_stream_t*) handle; req->cb = cb; + req->u.connect.pipeHandle = INVALID_HANDLE_VALUE; + req->u.connect.duplex_flags = 0; + + if (handle->flags & UV_HANDLE_PIPESERVER) { + err = ERROR_INVALID_PARAMETER; + goto error; + } + if (handle->flags & UV_HANDLE_CONNECTION) { + err = ERROR_PIPE_BUSY; + goto error; + } + uv__pipe_connection_init(handle); /* Convert name to UTF16. */ nameSize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0) * sizeof(WCHAR); @@ -888,19 +877,10 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, goto error; } - assert(pipeHandle != INVALID_HANDLE_VALUE); - - if (uv_set_pipe_handle(loop, - (uv_pipe_t*) req->handle, - pipeHandle, - -1, - duplex_flags)) { - err = GetLastError(); - goto error; - } - + req->u.connect.pipeHandle = pipeHandle; + req->u.connect.duplex_flags = duplex_flags; SET_REQ_SUCCESS(req); - uv_insert_pending_req(loop, (uv_req_t*) req); + uv__insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); return; @@ -916,7 +896,7 @@ error: /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, err); - uv_insert_pending_req(loop, (uv_req_t*) req); + uv__insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); return; @@ -937,7 +917,7 @@ void uv__pipe_interrupt_read(uv_pipe_t* handle) { /* Cancel asynchronous read. */ r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped); assert(r || GetLastError() == ERROR_NOT_FOUND); - + (void) r; } else { /* Cancel synchronous read (which is happening in the thread pool). */ HANDLE thread; @@ -973,17 +953,30 @@ void uv__pipe_interrupt_read(uv_pipe_t* handle) { void uv__pipe_read_stop(uv_pipe_t* handle) { handle->flags &= ~UV_HANDLE_READING; DECREASE_ACTIVE_COUNT(handle->loop, handle); - uv__pipe_interrupt_read(handle); } /* Cleans up uv_pipe_t (server or connection) and all resources associated with * it. */ -void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) { +void uv__pipe_close(uv_loop_t* loop, uv_pipe_t* handle) { int i; HANDLE pipeHandle; + if (handle->flags & UV_HANDLE_READING) { + handle->flags &= ~UV_HANDLE_READING; + DECREASE_ACTIVE_COUNT(loop, handle); + } + + if (handle->flags & UV_HANDLE_LISTENING) { + handle->flags &= ~UV_HANDLE_LISTENING; + DECREASE_ACTIVE_COUNT(loop, handle); + } + + handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); + + uv__handle_closing(handle); + uv__pipe_interrupt_read(handle); if (handle->name) { @@ -1003,45 +996,27 @@ void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) { } if (handle->flags & UV_HANDLE_CONNECTION) { - handle->flags &= ~UV_HANDLE_WRITABLE; eof_timer_destroy(handle); } if ((handle->flags & UV_HANDLE_CONNECTION) - && handle->handle != INVALID_HANDLE_VALUE) + && handle->handle != INVALID_HANDLE_VALUE) { + /* This will eventually destroy the write queue for us too. */ close_pipe(handle); -} - - -void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_READING) { - handle->flags &= ~UV_HANDLE_READING; - DECREASE_ACTIVE_COUNT(loop, handle); - } - - if (handle->flags & UV_HANDLE_LISTENING) { - handle->flags &= ~UV_HANDLE_LISTENING; - DECREASE_ACTIVE_COUNT(loop, handle); } - uv_pipe_cleanup(loop, handle); - - if (handle->reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); - } - - handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); - uv__handle_closing(handle); + if (handle->reqs_pending == 0) + uv__want_endgame(loop, (uv_handle_t*) handle); } -static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, +static void uv__pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, uv_pipe_accept_t* req, BOOL firstInstance) { assert(handle->flags & UV_HANDLE_LISTENING); if (!firstInstance && !pipe_alloc_accept(loop, handle, req, FALSE)) { SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*) req); + uv__insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; return; } @@ -1061,7 +1036,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, GetLastError()); } - uv_insert_pending_req(loop, (uv_req_t*) req); + uv__insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; return; } @@ -1071,7 +1046,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, } -int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { +int uv__pipe_accept(uv_pipe_t* server, uv_stream_t* client) { uv_loop_t* loop = server->loop; uv_pipe_t* pipe_client; uv_pipe_accept_t* req; @@ -1099,6 +1074,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { } else { pipe_client = (uv_pipe_t*) client; + uv__pipe_connection_init(pipe_client); /* Find a connection instance that has been connected, but not yet * accepted. */ @@ -1110,7 +1086,6 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { } /* Initialize the client handle and copy the pipeHandle to the client */ - uv_pipe_connection_init(pipe_client); pipe_client->handle = req->pipeHandle; pipe_client->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; @@ -1121,7 +1096,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { server->handle = INVALID_HANDLE_VALUE; if (!(server->flags & UV_HANDLE_CLOSING)) { - uv_pipe_queue_accept(loop, server, req, FALSE); + uv__pipe_queue_accept(loop, server, req, FALSE); } } @@ -1130,7 +1105,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { /* Starts listening for connections for the given pipe. */ -int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { +int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { uv_loop_t* loop = handle->loop; int i; @@ -1162,7 +1137,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { assert(handle->pipe.serv.accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE); for (i = 0; i < handle->pipe.serv.pending_instances; i++) { - uv_pipe_queue_accept(loop, handle, &handle->pipe.serv.accept_reqs[i], i == 0); + uv__pipe_queue_accept(loop, handle, &handle->pipe.serv.accept_reqs[i], i == 0); } return 0; @@ -1306,7 +1281,7 @@ static void CALLBACK post_completion_write_wait(void* context, BOOLEAN timed_out } -static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { +static void uv__pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { uv_read_t* req; int result; @@ -1365,15 +1340,15 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { return; error: - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); handle->flags |= UV_HANDLE_READ_PENDING; handle->reqs_pending++; } -int uv_pipe_read_start(uv_pipe_t* handle, - uv_alloc_cb alloc_cb, - uv_read_cb read_cb) { +int uv__pipe_read_start(uv_pipe_t* handle, + uv_alloc_cb alloc_cb, + uv_read_cb read_cb) { uv_loop_t* loop = handle->loop; handle->flags |= UV_HANDLE_READING; @@ -1391,14 +1366,14 @@ int uv_pipe_read_start(uv_pipe_t* handle, uv_fatal_error(GetLastError(), "CreateEvent"); } } - uv_pipe_queue_read(loop, handle); + uv__pipe_queue_read(loop, handle); } return 0; } -static void uv_insert_non_overlapped_write_req(uv_pipe_t* handle, +static void uv__insert_non_overlapped_write_req(uv_pipe_t* handle, uv_write_t* req) { req->next_req = NULL; if (handle->pipe.conn.non_overlapped_writes_tail) { @@ -1434,7 +1409,7 @@ static uv_write_t* uv_remove_non_overlapped_write_req(uv_pipe_t* handle) { } -static void uv_queue_non_overlapped_write(uv_pipe_t* handle) { +static void uv__queue_non_overlapped_write(uv_pipe_t* handle) { uv_write_t* req = uv_remove_non_overlapped_write_req(handle); if (req) { if (!QueueUserWorkItem(&uv_pipe_writefile_thread_proc, @@ -1575,9 +1550,9 @@ static int uv__pipe_write_data(uv_loop_t* loop, return 0; } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { req->write_buffer = write_buf; - uv_insert_non_overlapped_write_req(handle, req); + uv__insert_non_overlapped_write_req(handle, req); if (handle->stream.conn.write_reqs_pending == 0) { - uv_queue_non_overlapped_write(handle); + uv__queue_non_overlapped_write(handle); } /* Request queued by the kernel. */ @@ -1790,7 +1765,7 @@ int uv__pipe_write(uv_loop_t* loop, } -static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, +static void uv__pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, uv_buf_t buf) { /* If there is an eof timer running, we don't need it any more, so discard * it. */ @@ -1802,7 +1777,7 @@ static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, } -static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, +static void uv__pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, uv_buf_t buf) { /* If there is an eof timer running, we don't need it any more, so discard * it. */ @@ -1814,12 +1789,12 @@ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, } -static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, +static void uv__pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, int error, uv_buf_t buf) { if (error == ERROR_BROKEN_PIPE) { - uv_pipe_read_eof(loop, handle, buf); + uv__pipe_read_eof(loop, handle, buf); } else { - uv_pipe_read_error(loop, handle, error, buf); + uv__pipe_read_error(loop, handle, error, buf); } } @@ -1890,7 +1865,7 @@ static DWORD uv__pipe_read_data(uv_loop_t* loop, /* Read into the user buffer. */ if (!ReadFile(handle->handle, buf.base, max_bytes, &bytes_read, NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf); + uv__pipe_read_error_or_eof(loop, handle, GetLastError(), buf); return 0; /* Break out of read loop. */ } @@ -1977,14 +1952,14 @@ invalid: err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */ error: - uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_); + uv__pipe_read_error_or_eof(loop, handle, err, uv_null_buf_); return 0; /* Break out of read loop. */ } -void uv_process_pipe_read_req(uv_loop_t* loop, - uv_pipe_t* handle, - uv_req_t* req) { +void uv__process_pipe_read_req(uv_loop_t* loop, + uv_pipe_t* handle, + uv_req_t* req) { assert(handle->type == UV_NAMED_PIPE); handle->flags &= ~(UV_HANDLE_READ_PENDING | UV_HANDLE_CANCELLATION_PENDING); @@ -2005,7 +1980,7 @@ void uv_process_pipe_read_req(uv_loop_t* loop, * indicate an ERROR_OPERATION_ABORTED error. This error isn't relevant to * the user; we'll start a new zero-read at the end of this function. */ if (err != ERROR_OPERATION_ABORTED) - uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_); + uv__pipe_read_error_or_eof(loop, handle, err, uv_null_buf_); } else { /* The zero-read completed without error, indicating there is data @@ -2015,7 +1990,7 @@ void uv_process_pipe_read_req(uv_loop_t* loop, /* Get the number of bytes available. */ avail = 0; if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL)) - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); + uv__pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); /* Read until we've either read all the bytes available, or the 'reading' * flag is cleared. */ @@ -2044,12 +2019,12 @@ void uv_process_pipe_read_req(uv_loop_t* loop, /* Start another zero-read request if necessary. */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_pipe_queue_read(loop, handle); + uv__pipe_queue_read(loop, handle); } } -void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, +void uv__process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, uv_write_t* req) { int err; @@ -2091,26 +2066,25 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE && handle->pipe.conn.non_overlapped_writes_tail) { assert(handle->stream.conn.write_reqs_pending > 0); - uv_queue_non_overlapped_write(handle); + uv__queue_non_overlapped_write(handle); } - if (handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } + if (handle->stream.conn.write_reqs_pending == 0) + if (handle->flags & UV_HANDLE_SHUTTING) + uv__pipe_shutdown(loop, handle, handle->stream.conn.shutdown_req); DECREASE_PENDING_REQ_COUNT(handle); } -void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, +void uv__process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, uv_req_t* raw_req) { uv_pipe_accept_t* req = (uv_pipe_accept_t*) raw_req; assert(handle->type == UV_NAMED_PIPE); if (handle->flags & UV_HANDLE_CLOSING) { - /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */ + /* The req->pipeHandle should be freed already in uv__pipe_close(). */ assert(req->pipeHandle == INVALID_HANDLE_VALUE); DECREASE_PENDING_REQ_COUNT(handle); return; @@ -2130,7 +2104,7 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, req->pipeHandle = INVALID_HANDLE_VALUE; } if (!(handle->flags & UV_HANDLE_CLOSING)) { - uv_pipe_queue_accept(loop, handle, req, FALSE); + uv__pipe_queue_accept(loop, handle, req, FALSE); } } @@ -2138,54 +2112,74 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, } -void uv_process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, +void uv__process_pipe_connect_req(uv_loop_t* loop, uv_pipe_t* handle, uv_connect_t* req) { + HANDLE pipeHandle; + DWORD duplex_flags; int err; assert(handle->type == UV_NAMED_PIPE); UNREGISTER_HANDLE_REQ(loop, handle, req); - if (req->cb) { - err = 0; - if (REQ_SUCCESS(req)) { - uv_pipe_connection_init(handle); - } else { - err = GET_REQ_ERROR(req); - } - req->cb(req, uv_translate_sys_error(err)); + err = 0; + if (REQ_SUCCESS(req)) { + pipeHandle = req->u.connect.pipeHandle; + duplex_flags = req->u.connect.duplex_flags; + err = uv__set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags); + if (err) + CloseHandle(pipeHandle); + } else { + err = uv_translate_sys_error(GET_REQ_ERROR(req)); } + if (req->cb) + req->cb(req, err); + DECREASE_PENDING_REQ_COUNT(handle); } -void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, + +void uv__process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, uv_shutdown_t* req) { + int err; + assert(handle->type == UV_NAMED_PIPE); + /* Clear the shutdown_req field so we don't go here again. */ + handle->stream.conn.shutdown_req = NULL; + handle->flags &= ~UV_HANDLE_SHUTTING; UNREGISTER_HANDLE_REQ(loop, handle, req); - if (handle->flags & UV_HANDLE_READABLE) { - /* Initialize and optionally start the eof timer. Only do this if the pipe - * is readable and we haven't seen EOF come in ourselves. */ - eof_timer_init(handle); + if (handle->flags & UV_HANDLE_CLOSING) { + /* Already closing. Cancel the shutdown. */ + err = UV_ECANCELED; + } else if (!REQ_SUCCESS(req)) { + /* An error occurred in trying to shutdown gracefully. */ + err = uv_translate_sys_error(GET_REQ_ERROR(req)); + } else { + if (handle->flags & UV_HANDLE_READABLE) { + /* Initialize and optionally start the eof timer. Only do this if the pipe + * is readable and we haven't seen EOF come in ourselves. */ + eof_timer_init(handle); + + /* If reading start the timer right now. Otherwise uv__pipe_queue_read will + * start it. */ + if (handle->flags & UV_HANDLE_READ_PENDING) { + eof_timer_start(handle); + } - /* If reading start the timer right now. Otherwise uv_pipe_queue_read will - * start it. */ - if (handle->flags & UV_HANDLE_READ_PENDING) { - eof_timer_start(handle); + } else { + /* This pipe is not readable. We can just close it to let the other end + * know that we're done writing. */ + close_pipe(handle); } - - } else { - /* This pipe is not readable. We can just close it to let the other end - * know that we're done writing. */ - close_pipe(handle); + err = 0; } - if (req->cb) { - req->cb(req, 0); - } + if (req->cb) + req->cb(req, err); DECREASE_PENDING_REQ_COUNT(handle); } @@ -2200,7 +2194,8 @@ static void eof_timer_init(uv_pipe_t* pipe) { pipe->pipe.conn.eof_timer = (uv_timer_t*) uv__malloc(sizeof *pipe->pipe.conn.eof_timer); r = uv_timer_init(pipe->loop, pipe->pipe.conn.eof_timer); - assert(r == 0); /* timers can't fail */ + assert(r == 0); /* timers can't fail */ + (void) r; pipe->pipe.conn.eof_timer->data = pipe; uv_unref((uv_handle_t*) pipe->pipe.conn.eof_timer); } @@ -2231,9 +2226,9 @@ static void eof_timer_cb(uv_timer_t* timer) { assert(pipe->type == UV_NAMED_PIPE); /* This should always be true, since we start the timer only in - * uv_pipe_queue_read after successfully calling ReadFile, or in - * uv_process_pipe_shutdown_req if a read is pending, and we always - * immediately stop the timer in uv_process_pipe_read_req. */ + * uv__pipe_queue_read after successfully calling ReadFile, or in + * uv__process_pipe_shutdown_req if a read is pending, and we always + * immediately stop the timer in uv__process_pipe_read_req. */ assert(pipe->flags & UV_HANDLE_READ_PENDING); /* If there are many packets coming off the iocp then the timer callback may @@ -2254,7 +2249,7 @@ static void eof_timer_cb(uv_timer_t* timer) { /* Report the eof and update flags. This will get reported even if the user * stopped reading in the meantime. TODO: is that okay? */ - uv_pipe_read_eof(loop, pipe, uv_null_buf_); + uv__pipe_read_eof(loop, pipe, uv_null_buf_); } @@ -2280,10 +2275,16 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { IO_STATUS_BLOCK io_status; FILE_ACCESS_INFORMATION access; DWORD duplex_flags = 0; + int err; if (os_handle == INVALID_HANDLE_VALUE) return UV_EBADF; + if (pipe->flags & UV_HANDLE_PIPESERVER) + return UV_EINVAL; + if (pipe->flags & UV_HANDLE_CONNECTION) + return UV_EBUSY; + uv__pipe_connection_init(pipe); uv__once_init(); /* In order to avoid closing a stdio file descriptor 0-2, duplicate the * underlying OS handle and forget about the original fd. @@ -2300,6 +2301,7 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { FALSE, DUPLICATE_SAME_ACCESS)) return uv_translate_sys_error(GetLastError()); + assert(os_handle != INVALID_HANDLE_VALUE); file = -1; } @@ -2327,17 +2329,17 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { if (access.AccessFlags & FILE_READ_DATA) duplex_flags |= UV_HANDLE_READABLE; - if (os_handle == INVALID_HANDLE_VALUE || - uv_set_pipe_handle(pipe->loop, - pipe, - os_handle, - file, - duplex_flags) == -1) { - return UV_EINVAL; + err = uv__set_pipe_handle(pipe->loop, + pipe, + os_handle, + file, + duplex_flags); + if (err) { + if (file == -1) + CloseHandle(os_handle); + return err; } - uv_pipe_connection_init(pipe); - if (pipe->ipc) { assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); pipe->pipe.conn.ipc_remote_pid = uv_os_getppid(); @@ -2361,6 +2363,51 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) uv__once_init(); name_info = NULL; + if (handle->name != NULL) { + /* The user might try to query the name before we are connected, + * and this is just easier to return the cached value if we have it. */ + name_buf = handle->name; + name_len = wcslen(name_buf); + + /* check how much space we need */ + addrlen = WideCharToMultiByte(CP_UTF8, + 0, + name_buf, + name_len, + NULL, + 0, + NULL, + NULL); + if (!addrlen) { + *size = 0; + err = uv_translate_sys_error(GetLastError()); + return err; + } else if (addrlen >= *size) { + *size = addrlen + 1; + err = UV_ENOBUFS; + goto error; + } + + addrlen = WideCharToMultiByte(CP_UTF8, + 0, + name_buf, + name_len, + buffer, + addrlen, + NULL, + NULL); + if (!addrlen) { + *size = 0; + err = uv_translate_sys_error(GetLastError()); + return err; + } + + *size = addrlen; + buffer[addrlen] = '\0'; + + return 0; + } + if (handle->handle == INVALID_HANDLE_VALUE) { *size = 0; return UV_EINVAL; @@ -2498,6 +2545,11 @@ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { if (handle->handle != INVALID_HANDLE_VALUE) return uv__pipe_getname(handle, buffer, size); + if (handle->flags & UV_HANDLE_CONNECTION) { + if (handle->name != NULL) + return uv__pipe_getname(handle, buffer, size); + } + return UV_EBADF; } diff --git a/Utilities/cmlibuv/src/win/poll.c b/Utilities/cmlibuv/src/win/poll.c index 9d37759..bd531b0 100644 --- a/Utilities/cmlibuv/src/win/poll.c +++ b/Utilities/cmlibuv/src/win/poll.c @@ -34,7 +34,9 @@ static const GUID uv_msafd_provider_ids[UV_MSAFD_PROVIDER_COUNT] = { {0xf9eab0c0, 0x26d4, 0x11d0, {0xbb, 0xbf, 0x00, 0xaa, 0x00, 0x6c, 0x34, 0xe4}}, {0x9fc48064, 0x7298, 0x43e4, - {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}} + {0xb7, 0xbd, 0x18, 0x1f, 0x20, 0x89, 0x79, 0x2a}}, + {0xa00943d9, 0x9c2e, 0x4633, + {0x9b, 0x59, 0x00, 0x57, 0xa3, 0x16, 0x09, 0x94}} }; typedef struct uv_single_fd_set_s { @@ -122,14 +124,14 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { memset(&req->u.io.overlapped, 0, sizeof req->u.io.overlapped); - result = uv_msafd_poll((SOCKET) handle->peer_socket, - afd_poll_info, - afd_poll_info, - &req->u.io.overlapped); + result = uv__msafd_poll((SOCKET) handle->peer_socket, + afd_poll_info, + afd_poll_info, + &req->u.io.overlapped); if (result != 0 && WSAGetLastError() != WSA_IO_PENDING) { /* Queue this req, reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, req); + uv__insert_pending_req(loop, req); } } @@ -195,7 +197,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, } else if ((handle->flags & UV_HANDLE_CLOSING) && handle->submitted_events_1 == 0 && handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); + uv__want_endgame(loop, (uv_handle_t*) handle); } } @@ -357,7 +359,7 @@ static void uv__slow_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { WT_EXECUTELONGFUNCTION)) { /* Make this req pending, reporting an error. */ SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, req); + uv__insert_pending_req(loop, req); } } @@ -400,7 +402,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, } else if ((handle->flags & UV_HANDLE_CLOSING) && handle->submitted_events_1 == 0 && handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); + uv__want_endgame(loop, (uv_handle_t*) handle); } } @@ -524,7 +526,7 @@ int uv_poll_stop(uv_poll_t* handle) { } -void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) { +void uv__process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) { if (!(handle->flags & UV_HANDLE_POLL_SLOW)) { uv__fast_poll_process_poll_req(loop, handle, req); } else { @@ -533,7 +535,7 @@ void uv_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, uv_req_t* req) { } -int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) { +int uv__poll_close(uv_loop_t* loop, uv_poll_t* handle) { AFD_POLL_INFO afd_poll_info; DWORD error; int result; @@ -543,7 +545,7 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) { if (handle->submitted_events_1 == 0 && handle->submitted_events_2 == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); + uv__want_endgame(loop, (uv_handle_t*) handle); return 0; } @@ -559,10 +561,10 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) { afd_poll_info.Handles[0].Status = 0; afd_poll_info.Handles[0].Events = AFD_POLL_ALL; - result = uv_msafd_poll(handle->socket, - &afd_poll_info, - uv__get_afd_poll_info_dummy(), - uv__get_overlapped_dummy()); + result = uv__msafd_poll(handle->socket, + &afd_poll_info, + uv__get_afd_poll_info_dummy(), + uv__get_overlapped_dummy()); if (result == SOCKET_ERROR) { error = WSAGetLastError(); @@ -574,7 +576,7 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) { } -void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) { +void uv__poll_endgame(uv_loop_t* loop, uv_poll_t* handle) { assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); diff --git a/Utilities/cmlibuv/src/win/process.c b/Utilities/cmlibuv/src/win/process.c index 9ca4122..248b7ea 100644 --- a/Utilities/cmlibuv/src/win/process.c +++ b/Utilities/cmlibuv/src/win/process.c @@ -105,7 +105,7 @@ static void uv__init_global_job_handle(void) { } -static int uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) { +static int uv__utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) { int ws_len, r; WCHAR* ws; @@ -137,7 +137,7 @@ static int uv_utf8_to_utf16_alloc(const char* s, WCHAR** ws_ptr) { } -static void uv_process_init(uv_loop_t* loop, uv_process_t* handle) { +static void uv__process_init(uv_loop_t* loop, uv_process_t* handle) { uv__handle_init(loop, (uv_handle_t*) handle, UV_PROCESS); handle->exit_cb = NULL; handle->pid = 0; @@ -864,7 +864,7 @@ static void CALLBACK exit_wait_callback(void* data, BOOLEAN didTimeout) { /* Called on main thread after a child process has exited. */ -void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { +void uv__process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { int64_t exit_code; DWORD status; @@ -874,7 +874,7 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { /* If we're closing, don't call the exit callback. Just schedule a close * callback now. */ if (handle->flags & UV_HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*) handle); + uv__want_endgame(loop, (uv_handle_t*) handle); return; } @@ -902,7 +902,7 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { } -void uv_process_close(uv_loop_t* loop, uv_process_t* handle) { +void uv__process_close(uv_loop_t* loop, uv_process_t* handle) { uv__handle_closing(handle); if (handle->wait_handle != INVALID_HANDLE_VALUE) { @@ -918,12 +918,12 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) { } if (!handle->exit_cb_pending) { - uv_want_endgame(loop, (uv_handle_t*)handle); + uv__want_endgame(loop, (uv_handle_t*)handle); } } -void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) { +void uv__process_endgame(uv_loop_t* loop, uv_process_t* handle) { assert(!handle->exit_cb_pending); assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); @@ -948,7 +948,7 @@ int uv_spawn(uv_loop_t* loop, PROCESS_INFORMATION info; DWORD process_flags; - uv_process_init(loop, process); + uv__process_init(loop, process); process->exit_cb = options->exit_cb; if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) { @@ -975,7 +975,7 @@ int uv_spawn(uv_loop_t* loop, UV_PROCESS_WINDOWS_HIDE_GUI | UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); - err = uv_utf8_to_utf16_alloc(options->file, &application); + err = uv__utf8_to_utf16_alloc(options->file, &application); if (err) goto done; @@ -994,7 +994,7 @@ int uv_spawn(uv_loop_t* loop, if (options->cwd) { /* Explicit cwd */ - err = uv_utf8_to_utf16_alloc(options->cwd, &cwd); + err = uv__utf8_to_utf16_alloc(options->cwd, &cwd); if (err) goto done; diff --git a/Utilities/cmlibuv/src/win/req-inl.h b/Utilities/cmlibuv/src/win/req-inl.h index f2513b7..9e20759 100644 --- a/Utilities/cmlibuv/src/win/req-inl.h +++ b/Utilities/cmlibuv/src/win/req-inl.h @@ -50,7 +50,7 @@ (pRtlNtStatusToDosError(GET_REQ_STATUS((req)))) #define GET_REQ_SOCK_ERROR(req) \ - (uv_ntstatus_to_winsock_error(GET_REQ_STATUS((req)))) + (uv__ntstatus_to_winsock_error(GET_REQ_STATUS((req)))) #define REGISTER_HANDLE_REQ(loop, handle, req) \ @@ -82,12 +82,12 @@ } -INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) { +INLINE static uv_req_t* uv__overlapped_to_req(OVERLAPPED* overlapped) { return CONTAINING_RECORD(overlapped, uv_req_t, u.io.overlapped); } -INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { +INLINE static void uv__insert_pending_req(uv_loop_t* loop, uv_req_t* req) { req->next_req = NULL; if (loop->pending_reqs_tail) { #ifdef _DEBUG @@ -115,19 +115,19 @@ INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { do { \ switch (((uv_handle_t*) (req)->handle_at)->type) { \ case UV_TCP: \ - uv_process_tcp_##method##_req(loop, \ + uv__process_tcp_##method##_req(loop, \ (uv_tcp_t*) ((req)->handle_at), \ req); \ break; \ \ case UV_NAMED_PIPE: \ - uv_process_pipe_##method##_req(loop, \ + uv__process_pipe_##method##_req(loop, \ (uv_pipe_t*) ((req)->handle_at), \ req); \ break; \ \ case UV_TTY: \ - uv_process_tty_##method##_req(loop, \ + uv__process_tty_##method##_req(loop, \ (uv_tty_t*) ((req)->handle_at), \ req); \ break; \ @@ -138,13 +138,13 @@ INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { } while (0) -INLINE static int uv_process_reqs(uv_loop_t* loop) { +INLINE static void uv__process_reqs(uv_loop_t* loop) { uv_req_t* req; uv_req_t* first; uv_req_t* next; if (loop->pending_reqs_tail == NULL) - return 0; + return; first = loop->pending_reqs_tail->next_req; next = first; @@ -172,50 +172,43 @@ INLINE static int uv_process_reqs(uv_loop_t* loop) { break; case UV_SHUTDOWN: - /* Tcp shutdown requests don't come here. */ - assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE); - uv_process_pipe_shutdown_req( - loop, - (uv_pipe_t*) ((uv_shutdown_t*) req)->handle, - (uv_shutdown_t*) req); + DELEGATE_STREAM_REQ(loop, (uv_shutdown_t*) req, shutdown, handle); break; case UV_UDP_RECV: - uv_process_udp_recv_req(loop, (uv_udp_t*) req->data, req); + uv__process_udp_recv_req(loop, (uv_udp_t*) req->data, req); break; case UV_UDP_SEND: - uv_process_udp_send_req(loop, - ((uv_udp_send_t*) req)->handle, - (uv_udp_send_t*) req); + uv__process_udp_send_req(loop, + ((uv_udp_send_t*) req)->handle, + (uv_udp_send_t*) req); break; case UV_WAKEUP: - uv_process_async_wakeup_req(loop, (uv_async_t*) req->data, req); + uv__process_async_wakeup_req(loop, (uv_async_t*) req->data, req); break; case UV_SIGNAL_REQ: - uv_process_signal_req(loop, (uv_signal_t*) req->data, req); + uv__process_signal_req(loop, (uv_signal_t*) req->data, req); break; case UV_POLL_REQ: - uv_process_poll_req(loop, (uv_poll_t*) req->data, req); + uv__process_poll_req(loop, (uv_poll_t*) req->data, req); break; case UV_PROCESS_EXIT: - uv_process_proc_exit(loop, (uv_process_t*) req->data); + uv__process_proc_exit(loop, (uv_process_t*) req->data); break; case UV_FS_EVENT_REQ: - uv_process_fs_event_req(loop, req, (uv_fs_event_t*) req->data); + uv__process_fs_event_req(loop, req, (uv_fs_event_t*) req->data); break; default: assert(0); } } - - return 1; } #endif /* UV_WIN_REQ_INL_H_ */ diff --git a/Utilities/cmlibuv/src/win/signal.c b/Utilities/cmlibuv/src/win/signal.c index 3d9f92c..8c79871 100644 --- a/Utilities/cmlibuv/src/win/signal.c +++ b/Utilities/cmlibuv/src/win/signal.c @@ -39,7 +39,7 @@ int uv__signal_start(uv_signal_t* handle, int signum, int oneshot); -void uv_signals_init(void) { +void uv__signals_init(void) { InitializeCriticalSection(&uv__signal_lock); if (!SetConsoleCtrlHandler(uv__signal_control_handler, TRUE)) abort(); @@ -231,7 +231,7 @@ int uv__signal_start(uv_signal_t* handle, } -void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, +void uv__process_signal_req(uv_loop_t* loop, uv_signal_t* handle, uv_req_t* req) { long dispatched_signum; @@ -254,22 +254,22 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, if (handle->flags & UV_HANDLE_CLOSING) { /* When it is closing, it must be stopped at this point. */ assert(handle->signum == 0); - uv_want_endgame(loop, (uv_handle_t*) handle); + uv__want_endgame(loop, (uv_handle_t*) handle); } } -void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) { +void uv__signal_close(uv_loop_t* loop, uv_signal_t* handle) { uv_signal_stop(handle); uv__handle_closing(handle); if (handle->pending_signum == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); + uv__want_endgame(loop, (uv_handle_t*) handle); } } -void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) { +void uv__signal_endgame(uv_loop_t* loop, uv_signal_t* handle) { assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); diff --git a/Utilities/cmlibuv/src/win/stream-inl.h b/Utilities/cmlibuv/src/win/stream-inl.h index 40f5ddd..91b1e78 100644 --- a/Utilities/cmlibuv/src/win/stream-inl.h +++ b/Utilities/cmlibuv/src/win/stream-inl.h @@ -30,9 +30,9 @@ #include "req-inl.h" -INLINE static void uv_stream_init(uv_loop_t* loop, - uv_stream_t* handle, - uv_handle_type type) { +INLINE static void uv__stream_init(uv_loop_t* loop, + uv_stream_t* handle, + uv_handle_type type) { uv__handle_init(loop, (uv_handle_t*) handle, type); handle->write_queue_size = 0; handle->activecnt = 0; @@ -46,7 +46,7 @@ INLINE static void uv_stream_init(uv_loop_t* loop, } -INLINE static void uv_connection_init(uv_stream_t* handle) { +INLINE static void uv__connection_init(uv_stream_t* handle) { handle->flags |= UV_HANDLE_CONNECTION; } diff --git a/Utilities/cmlibuv/src/win/stream.c b/Utilities/cmlibuv/src/win/stream.c index abf477f..292bf58 100644 --- a/Utilities/cmlibuv/src/win/stream.c +++ b/Utilities/cmlibuv/src/win/stream.c @@ -29,14 +29,16 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) { int err; - + if (uv__is_closing(stream)) { + return UV_EINVAL; + } err = ERROR_INVALID_PARAMETER; switch (stream->type) { case UV_TCP: - err = uv_tcp_listen((uv_tcp_t*)stream, backlog, cb); + err = uv__tcp_listen((uv_tcp_t*)stream, backlog, cb); break; case UV_NAMED_PIPE: - err = uv_pipe_listen((uv_pipe_t*)stream, backlog, cb); + err = uv__pipe_listen((uv_pipe_t*)stream, backlog, cb); break; default: assert(0); @@ -52,10 +54,10 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) { err = ERROR_INVALID_PARAMETER; switch (server->type) { case UV_TCP: - err = uv_tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client); + err = uv__tcp_accept((uv_tcp_t*)server, (uv_tcp_t*)client); break; case UV_NAMED_PIPE: - err = uv_pipe_accept((uv_pipe_t*)server, client); + err = uv__pipe_accept((uv_pipe_t*)server, client); break; default: assert(0); @@ -73,13 +75,13 @@ int uv__read_start(uv_stream_t* handle, err = ERROR_INVALID_PARAMETER; switch (handle->type) { case UV_TCP: - err = uv_tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb); + err = uv__tcp_read_start((uv_tcp_t*)handle, alloc_cb, read_cb); break; case UV_NAMED_PIPE: - err = uv_pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb); + err = uv__pipe_read_start((uv_pipe_t*)handle, alloc_cb, read_cb); break; case UV_TTY: - err = uv_tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb); + err = uv__tty_read_start((uv_tty_t*) handle, alloc_cb, read_cb); break; default: assert(0); @@ -97,7 +99,7 @@ int uv_read_stop(uv_stream_t* handle) { err = 0; if (handle->type == UV_TTY) { - err = uv_tty_read_stop((uv_tty_t*) handle); + err = uv__tty_read_stop((uv_tty_t*) handle); } else if (handle->type == UV_NAMED_PIPE) { uv__pipe_read_stop((uv_pipe_t*) handle); } else { @@ -124,14 +126,14 @@ int uv_write(uv_write_t* req, err = ERROR_INVALID_PARAMETER; switch (handle->type) { case UV_TCP: - err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb); + err = uv__tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb); break; case UV_NAMED_PIPE: err = uv__pipe_write( loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb); break; case UV_TTY: - err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb); + err = uv__tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb); break; default: assert(0); @@ -217,7 +219,12 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); - uv_want_endgame(loop, (uv_handle_t*)handle); + if (handle->stream.conn.write_reqs_pending == 0) { + if (handle->type == UV_NAMED_PIPE) + uv__pipe_shutdown(loop, (uv_pipe_t*) handle, req); + else + uv__insert_pending_req(loop, (uv_req_t*) req); + } return 0; } diff --git a/Utilities/cmlibuv/src/win/tcp.c b/Utilities/cmlibuv/src/win/tcp.c index 6ca11e0..b6aa4c5 100644 --- a/Utilities/cmlibuv/src/win/tcp.c +++ b/Utilities/cmlibuv/src/win/tcp.c @@ -78,11 +78,11 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign } -static int uv_tcp_set_socket(uv_loop_t* loop, - uv_tcp_t* handle, - SOCKET socket, - int family, - int imported) { +static int uv__tcp_set_socket(uv_loop_t* loop, + uv_tcp_t* handle, + SOCKET socket, + int family, + int imported) { DWORD yes = 1; int non_ifs_lsp; int err; @@ -162,7 +162,7 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) { if (flags & ~0xFF) return UV_EINVAL; - uv_stream_init(loop, (uv_stream_t*) handle, UV_TCP); + uv__stream_init(loop, (uv_stream_t*) handle, UV_TCP); handle->tcp.serv.accept_reqs = NULL; handle->tcp.serv.pending_accepts = NULL; handle->socket = INVALID_SOCKET; @@ -173,7 +173,7 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) { handle->delayed_error = 0; /* If anything fails beyond this point we need to remove the handle from - * the handle queue, since it was added by uv__handle_init in uv_stream_init. + * the handle queue, since it was added by uv__handle_init in uv__stream_init. */ if (domain != AF_UNSPEC) { @@ -187,7 +187,7 @@ int uv_tcp_init_ex(uv_loop_t* loop, uv_tcp_t* handle, unsigned int flags) { return uv_translate_sys_error(err); } - err = uv_tcp_set_socket(handle->loop, handle, sock, domain, 0); + err = uv__tcp_set_socket(handle->loop, handle, sock, domain, 0); if (err) { closesocket(sock); QUEUE_REMOVE(&handle->handle_queue); @@ -205,73 +205,76 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { } -void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { +void uv__process_tcp_shutdown_req(uv_loop_t* loop, uv_tcp_t* stream, uv_shutdown_t *req) { int err; - unsigned int i; - uv_tcp_accept_t* req; - if (handle->flags & UV_HANDLE_CONNECTION && - handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { + assert(req); + assert(stream->stream.conn.write_reqs_pending == 0); + assert(!(stream->flags & UV_HANDLE_SHUT)); + assert(stream->flags & UV_HANDLE_CONNECTION); - UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req); + stream->stream.conn.shutdown_req = NULL; + stream->flags &= ~UV_HANDLE_SHUTTING; + UNREGISTER_HANDLE_REQ(loop, stream, req); - err = 0; - if (handle->flags & UV_HANDLE_CLOSING) { - err = ERROR_OPERATION_ABORTED; - } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) { - err = WSAGetLastError(); - } + err = 0; + if (stream->flags & UV_HANDLE_CLOSING) + /* The user destroyed the stream before we got to do the shutdown. */ + err = UV_ECANCELED; + else if (shutdown(stream->socket, SD_SEND) == SOCKET_ERROR) + err = uv_translate_sys_error(WSAGetLastError()); + else /* Success. */ + stream->flags |= UV_HANDLE_SHUT; + + if (req->cb) + req->cb(req, err); - if (handle->stream.conn.shutdown_req->cb) { - handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, - uv_translate_sys_error(err)); - } + DECREASE_PENDING_REQ_COUNT(stream); +} - handle->stream.conn.shutdown_req = NULL; - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - if (handle->flags & UV_HANDLE_CLOSING && - handle->reqs_pending == 0) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - assert(handle->socket == INVALID_SOCKET); +void uv__tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { + unsigned int i; + uv_tcp_accept_t* req; + + assert(handle->flags & UV_HANDLE_CLOSING); + assert(handle->reqs_pending == 0); + assert(!(handle->flags & UV_HANDLE_CLOSED)); + assert(handle->socket == INVALID_SOCKET); - if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) { - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - for (i = 0; i < uv_simultaneous_server_accepts; i++) { - req = &handle->tcp.serv.accept_reqs[i]; - if (req->wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(req->wait_handle); - req->wait_handle = INVALID_HANDLE_VALUE; - } - if (req->event_handle != NULL) { - CloseHandle(req->event_handle); - req->event_handle = NULL; - } + if (!(handle->flags & UV_HANDLE_CONNECTION) && handle->tcp.serv.accept_reqs) { + if (handle->flags & UV_HANDLE_EMULATE_IOCP) { + for (i = 0; i < uv_simultaneous_server_accepts; i++) { + req = &handle->tcp.serv.accept_reqs[i]; + if (req->wait_handle != INVALID_HANDLE_VALUE) { + UnregisterWait(req->wait_handle); + req->wait_handle = INVALID_HANDLE_VALUE; + } + if (req->event_handle != NULL) { + CloseHandle(req->event_handle); + req->event_handle = NULL; } } - - uv__free(handle->tcp.serv.accept_reqs); - handle->tcp.serv.accept_reqs = NULL; } - if (handle->flags & UV_HANDLE_CONNECTION && - handle->flags & UV_HANDLE_EMULATE_IOCP) { - if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { - UnregisterWait(handle->read_req.wait_handle); - handle->read_req.wait_handle = INVALID_HANDLE_VALUE; - } - if (handle->read_req.event_handle != NULL) { - CloseHandle(handle->read_req.event_handle); - handle->read_req.event_handle = NULL; - } - } + uv__free(handle->tcp.serv.accept_reqs); + handle->tcp.serv.accept_reqs = NULL; + } - uv__handle_close(handle); - loop->active_tcp_streams--; + if (handle->flags & UV_HANDLE_CONNECTION && + handle->flags & UV_HANDLE_EMULATE_IOCP) { + if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { + UnregisterWait(handle->read_req.wait_handle); + handle->read_req.wait_handle = INVALID_HANDLE_VALUE; + } + if (handle->read_req.event_handle != NULL) { + CloseHandle(handle->read_req.event_handle); + handle->read_req.event_handle = NULL; + } } + + uv__handle_close(handle); + loop->active_tcp_streams--; } @@ -286,10 +289,10 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { * See issue #1360. * */ -static int uv_tcp_try_bind(uv_tcp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { +static int uv__tcp_try_bind(uv_tcp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen, + unsigned int flags) { DWORD err; int r; @@ -305,7 +308,7 @@ static int uv_tcp_try_bind(uv_tcp_t* handle, return WSAGetLastError(); } - err = uv_tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0); + err = uv__tcp_set_socket(handle->loop, handle, sock, addr->sa_family, 0); if (err) { closesocket(sock); return err; @@ -385,7 +388,7 @@ static void CALLBACK post_write_completion(void* context, BOOLEAN timed_out) { } -static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { +static void uv__tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { uv_loop_t* loop = handle->loop; BOOL success; DWORD bytes; @@ -406,7 +409,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { accept_socket = socket(family, SOCK_STREAM, 0); if (accept_socket == INVALID_SOCKET) { SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; return; } @@ -414,7 +417,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE) accept_socket, HANDLE_FLAG_INHERIT, 0)) { SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; closesocket(accept_socket); return; @@ -440,7 +443,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { /* Process the req without IOCP. */ req->accept_socket = accept_socket; handle->reqs_pending++; - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(success)) { /* The req will be processed with IOCP. */ req->accept_socket = accept_socket; @@ -451,12 +454,12 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { req->event_handle, post_completion, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } } else { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); handle->reqs_pending++; /* Destroy the preallocated client socket. */ closesocket(accept_socket); @@ -469,7 +472,7 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { } -static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { +static void uv__tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { uv_read_t* req; uv_buf_t buf; int result; @@ -524,7 +527,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { if (UV_SUCCEEDED_WITHOUT_IOCP(result == 0)) { /* Process the req without IOCP. */ req->u.io.overlapped.InternalHigh = bytes; - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* The req will be processed with IOCP. */ if (handle->flags & UV_HANDLE_EMULATE_IOCP && @@ -533,12 +536,12 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { req->event_handle, post_completion, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } } else { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } } @@ -558,7 +561,7 @@ int uv_tcp_close_reset(uv_tcp_t* handle, uv_close_cb close_cb) { } -int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { +int uv__tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { unsigned int i, simultaneous_accepts; uv_tcp_accept_t* req; int err; @@ -578,10 +581,10 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { } if (!(handle->flags & UV_HANDLE_BOUND)) { - err = uv_tcp_try_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - 0); + err = uv__tcp_try_bind(handle, + (const struct sockaddr*) &uv_addr_ip4_any_, + sizeof(uv_addr_ip4_any_), + 0); if (err) return err; if (handle->delayed_error) @@ -589,7 +592,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { } if (!handle->tcp.serv.func_acceptex) { - if (!uv_get_acceptex_function(handle->socket, &handle->tcp.serv.func_acceptex)) { + if (!uv__get_acceptex_function(handle->socket, &handle->tcp.serv.func_acceptex)) { return WSAEAFNOSUPPORT; } } @@ -630,7 +633,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { req->event_handle = NULL; } - uv_tcp_queue_accept(handle, req); + uv__tcp_queue_accept(handle, req); } /* Initialize other unused requests too, because uv_tcp_endgame doesn't @@ -650,7 +653,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { } -int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { +int uv__tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { uv_loop_t* loop = server->loop; int err = 0; int family; @@ -672,7 +675,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { family = AF_INET; } - err = uv_tcp_set_socket(client->loop, + err = uv__tcp_set_socket(client->loop, client, req->accept_socket, family, @@ -680,7 +683,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { if (err) { closesocket(req->accept_socket); } else { - uv_connection_init((uv_stream_t*) client); + uv__connection_init((uv_stream_t*) client); /* AcceptEx() implicitly binds the accepted socket. */ client->flags |= UV_HANDLE_BOUND | UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } @@ -693,7 +696,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { if (!(server->flags & UV_HANDLE_CLOSING)) { /* Check if we're in a middle of changing the number of pending accepts. */ if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) { - uv_tcp_queue_accept(server, req); + uv__tcp_queue_accept(server, req); } else { /* We better be switching to a single pending accept. */ assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT); @@ -706,7 +709,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { * All previously queued accept requests are now processed. * We now switch to queueing just a single accept. */ - uv_tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]); + uv__tcp_queue_accept(server, &server->tcp.serv.accept_reqs[0]); server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING; server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; } @@ -719,7 +722,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { } -int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, +int uv__tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb) { uv_loop_t* loop = handle->loop; @@ -738,7 +741,7 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, uv_fatal_error(GetLastError(), "CreateEvent"); } } - uv_tcp_queue_read(loop, handle); + uv__tcp_queue_read(loop, handle); } return 0; @@ -779,7 +782,7 @@ static int uv__is_fast_loopback_fail_supported(void) { return os_info.dwBuildNumber >= 16299; } -static int uv_tcp_try_connect(uv_connect_t* req, +static int uv__tcp_try_connect(uv_connect_t* req, uv_tcp_t* handle, const struct sockaddr* addr, unsigned int addrlen, @@ -807,7 +810,7 @@ static int uv_tcp_try_connect(uv_connect_t* req, } else { abort(); } - err = uv_tcp_try_bind(handle, bind_addr, addrlen, 0); + err = uv__tcp_try_bind(handle, bind_addr, addrlen, 0); if (err) return err; if (handle->delayed_error != 0) @@ -815,7 +818,7 @@ static int uv_tcp_try_connect(uv_connect_t* req, } if (!handle->tcp.conn.func_connectex) { - if (!uv_get_connectex_function(handle->socket, &handle->tcp.conn.func_connectex)) { + if (!uv__get_connectex_function(handle->socket, &handle->tcp.conn.func_connectex)) { return WSAEAFNOSUPPORT; } } @@ -850,7 +853,7 @@ out: /* Process the req without IOCP. */ handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); return 0; } @@ -866,7 +869,7 @@ out: /* Process the req without IOCP. */ handle->reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(success)) { /* The req will be processed with IOCP. */ handle->reqs_pending++; @@ -903,7 +906,7 @@ int uv_tcp_getpeername(const uv_tcp_t* handle, } -int uv_tcp_write(uv_loop_t* loop, +int uv__tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle, const uv_buf_t bufs[], @@ -941,7 +944,7 @@ int uv_tcp_write(uv_loop_t* loop, handle->reqs_pending++; handle->stream.conn.write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*) req); + uv__insert_pending_req(loop, (uv_req_t*) req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* Request queued by the kernel. */ req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs); @@ -954,7 +957,7 @@ int uv_tcp_write(uv_loop_t* loop, req->event_handle, post_write_completion, (void*) req, INFINITE, WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE)) { SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } } else { /* Send failed due to an error, report it later */ @@ -963,7 +966,7 @@ int uv_tcp_write(uv_loop_t* loop, handle->stream.conn.write_reqs_pending++; REGISTER_HANDLE_REQ(loop, handle, req); SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, (uv_req_t*) req); + uv__insert_pending_req(loop, (uv_req_t*) req); } return 0; @@ -994,7 +997,7 @@ int uv__tcp_try_write(uv_tcp_t* handle, } -void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, +void uv__process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* req) { DWORD bytes, flags, err; uv_buf_t buf; @@ -1115,7 +1118,7 @@ done: /* Post another read if still reading and not closing. */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_tcp_queue_read(loop, handle); + uv__tcp_queue_read(loop, handle); } } @@ -1123,7 +1126,7 @@ done: } -void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, +void uv__process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, uv_write_t* req) { int err; @@ -1160,16 +1163,17 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle, closesocket(handle->socket); handle->socket = INVALID_SOCKET; } - if (handle->stream.conn.shutdown_req != NULL) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } + if (handle->flags & UV_HANDLE_SHUTTING) + uv__process_tcp_shutdown_req(loop, + handle, + handle->stream.conn.shutdown_req); } DECREASE_PENDING_REQ_COUNT(handle); } -void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, +void uv__process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, uv_req_t* raw_req) { uv_tcp_accept_t* req = (uv_tcp_accept_t*) raw_req; int err; @@ -1209,7 +1213,7 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, closesocket(req->accept_socket); req->accept_socket = INVALID_SOCKET; if (handle->flags & UV_HANDLE_LISTENING) { - uv_tcp_queue_accept(handle, req); + uv__tcp_queue_accept(handle, req); } } @@ -1217,7 +1221,7 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, } -void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, +void uv__process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, uv_connect_t* req) { int err; @@ -1242,7 +1246,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0) { - uv_connection_init((uv_stream_t*)handle); + uv__connection_init((uv_stream_t*)handle); handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; loop->active_tcp_streams++; } else { @@ -1312,7 +1316,7 @@ int uv__tcp_xfer_import(uv_tcp_t* tcp, return WSAGetLastError(); } - err = uv_tcp_set_socket( + err = uv__tcp_set_socket( tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1); if (err) { closesocket(socket); @@ -1323,7 +1327,7 @@ int uv__tcp_xfer_import(uv_tcp_t* tcp, tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET; if (xfer_type == UV__IPC_SOCKET_XFER_TCP_CONNECTION) { - uv_connection_init((uv_stream_t*)tcp); + uv__connection_init((uv_stream_t*)tcp); tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } @@ -1404,14 +1408,14 @@ int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { } -static void uv_tcp_try_cancel_reqs(uv_tcp_t* tcp) { +static void uv__tcp_try_cancel_reqs(uv_tcp_t* tcp) { SOCKET socket; int non_ifs_lsp; int reading; int writing; socket = tcp->socket; - reading = tcp->flags & UV_HANDLE_READING; + reading = tcp->flags & UV_HANDLE_READ_PENDING; writing = tcp->stream.conn.write_reqs_pending > 0; if (!reading && !writing) return; @@ -1456,12 +1460,12 @@ static void uv_tcp_try_cancel_reqs(uv_tcp_t* tcp) { } -void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { +void uv__tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { if (tcp->flags & UV_HANDLE_CONNECTION) { - uv_tcp_try_cancel_reqs(tcp); if (tcp->flags & UV_HANDLE_READING) { uv_read_stop((uv_stream_t*) tcp); } + uv__tcp_try_cancel_reqs(tcp); } else { if (tcp->tcp.serv.accept_reqs != NULL) { /* First close the incoming sockets to cancel the accept operations before @@ -1483,6 +1487,9 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { DECREASE_ACTIVE_COUNT(loop, tcp); } + tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); + uv__handle_closing(tcp); + /* If any overlapped req failed to cancel, calling `closesocket` now would * cause Win32 to send an RST packet. Try to avoid that for writes, if * possibly applicable, by waiting to process the completion notifications @@ -1494,12 +1501,8 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { tcp->socket = INVALID_SOCKET; } - tcp->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); - uv__handle_closing(tcp); - - if (tcp->reqs_pending == 0) { - uv_want_endgame(tcp->loop, (uv_handle_t*)tcp); - } + if (tcp->reqs_pending == 0) + uv__want_endgame(loop, (uv_handle_t*) tcp); } @@ -1520,7 +1523,7 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { return uv_translate_sys_error(GetLastError()); } - err = uv_tcp_set_socket(handle->loop, + err = uv__tcp_set_socket(handle->loop, handle, sock, protocol_info.iAddressFamily, @@ -1537,7 +1540,7 @@ int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { saddr_len = sizeof(saddr); if (!uv_tcp_getpeername(handle, (struct sockaddr*) &saddr, &saddr_len)) { /* Socket is already connected. */ - uv_connection_init((uv_stream_t*) handle); + uv__connection_init((uv_stream_t*) handle); handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } } @@ -1555,7 +1558,7 @@ int uv__tcp_bind(uv_tcp_t* handle, unsigned int flags) { int err; - err = uv_tcp_try_bind(handle, addr, addrlen, flags); + err = uv__tcp_try_bind(handle, addr, addrlen, flags); if (err) return uv_translate_sys_error(err); @@ -1573,7 +1576,7 @@ int uv__tcp_connect(uv_connect_t* req, uv_connect_cb cb) { int err; - err = uv_tcp_try_connect(req, handle, addr, addrlen, cb); + err = uv__tcp_try_connect(req, handle, addr, addrlen, cb); if (err) return uv_translate_sys_error(err); @@ -1634,7 +1637,7 @@ int uv_socketpair(int type, int protocol, uv_os_sock_t fds[2], int flags0, int f goto wsaerror; if (!SetHandleInformation((HANDLE) client1, HANDLE_FLAG_INHERIT, 0)) goto error; - if (!uv_get_acceptex_function(server, &func_acceptex)) { + if (!uv__get_acceptex_function(server, &func_acceptex)) { err = WSAEAFNOSUPPORT; goto cleanup; } diff --git a/Utilities/cmlibuv/src/win/thread.c b/Utilities/cmlibuv/src/win/thread.c index ea5dc04..d3b1c96 100644 --- a/Utilities/cmlibuv/src/win/thread.c +++ b/Utilities/cmlibuv/src/win/thread.c @@ -182,8 +182,9 @@ int uv_thread_create_ex(uv_thread_t* tid, uv_thread_t uv_thread_self(void) { + uv_thread_t key; uv_once(&uv__current_thread_init_guard, uv__init_current_thread_key); - uv_thread_t key = uv_key_get(&uv__current_thread_key); + key = uv_key_get(&uv__current_thread_key); if (key == NULL) { /* If the thread wasn't started by uv_thread_create (such as the main * thread), we assign an id to it now. */ diff --git a/Utilities/cmlibuv/src/win/tty.c b/Utilities/cmlibuv/src/win/tty.c index 1b9d4f8..267ca64 100644 --- a/Utilities/cmlibuv/src/win/tty.c +++ b/Utilities/cmlibuv/src/win/tty.c @@ -67,10 +67,10 @@ #define CURSOR_SIZE_SMALL 25 #define CURSOR_SIZE_LARGE 100 -static void uv_tty_capture_initial_style( +static void uv__tty_capture_initial_style( CONSOLE_SCREEN_BUFFER_INFO* screen_buffer_info, CONSOLE_CURSOR_INFO* cursor_info); -static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info); +static void uv__tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info); static int uv__cancel_read_console(uv_tty_t* handle); @@ -163,7 +163,7 @@ static BOOL uv__need_check_vterm_state = TRUE; static uv_tty_vtermstate_t uv__vterm_state = UV_TTY_UNSUPPORTED; static void uv__determine_vterm_state(HANDLE handle); -void uv_console_init(void) { +void uv__console_init(void) { if (uv_sem_init(&uv_tty_output_lock, 1)) abort(); uv__tty_console_handle = CreateFileW(L"CONOUT$", @@ -238,16 +238,16 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) { uv__determine_vterm_state(handle); /* Remember the original console text attributes and cursor info. */ - uv_tty_capture_initial_style(&screen_buffer_info, &cursor_info); + uv__tty_capture_initial_style(&screen_buffer_info, &cursor_info); - uv_tty_update_virtual_window(&screen_buffer_info); + uv__tty_update_virtual_window(&screen_buffer_info); uv_sem_post(&uv_tty_output_lock); } - uv_stream_init(loop, (uv_stream_t*) tty, UV_TTY); - uv_connection_init((uv_stream_t*) tty); + uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); + uv__connection_init((uv_stream_t*) tty); tty->handle = handle; tty->u.fd = fd; @@ -289,7 +289,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int unused) { /* Set the default console text attributes based on how the console was * configured when libuv started. */ -static void uv_tty_capture_initial_style( +static void uv__tty_capture_initial_style( CONSOLE_SCREEN_BUFFER_INFO* screen_buffer_info, CONSOLE_CURSOR_INFO* cursor_info) { static int style_captured = 0; @@ -380,7 +380,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { was_reading = 1; alloc_cb = tty->alloc_cb; read_cb = tty->read_cb; - err = uv_tty_read_stop(tty); + err = uv__tty_read_stop(tty); if (err) { return uv_translate_sys_error(err); } @@ -404,7 +404,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { /* If we just stopped reading, restart. */ if (was_reading) { - err = uv_tty_read_start(tty, alloc_cb, read_cb); + err = uv__tty_read_start(tty, alloc_cb, read_cb); if (err) { return uv_translate_sys_error(err); } @@ -422,7 +422,7 @@ int uv_tty_get_winsize(uv_tty_t* tty, int* width, int* height) { } uv_sem_wait(&uv_tty_output_lock); - uv_tty_update_virtual_window(&info); + uv__tty_update_virtual_window(&info); uv_sem_post(&uv_tty_output_lock); *width = uv_tty_virtual_width; @@ -452,7 +452,7 @@ static void CALLBACK uv_tty_post_raw_read(void* data, BOOLEAN didTimeout) { } -static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) { +static void uv__tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) { uv_read_t* req; BOOL r; @@ -475,7 +475,7 @@ static void uv_tty_queue_read_raw(uv_loop_t* loop, uv_tty_t* handle) { if (!r) { handle->tty.rd.read_raw_wait = NULL; SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } handle->flags |= UV_HANDLE_READ_PENDING; @@ -579,7 +579,7 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { } -static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) { +static void uv__tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) { uv_read_t* req; BOOL r; @@ -611,7 +611,7 @@ static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) { WT_EXECUTELONGFUNCTION); if (!r) { SET_REQ_ERROR(req, GetLastError()); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } handle->flags |= UV_HANDLE_READ_PENDING; @@ -619,11 +619,11 @@ static void uv_tty_queue_read_line(uv_loop_t* loop, uv_tty_t* handle) { } -static void uv_tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) { +static void uv__tty_queue_read(uv_loop_t* loop, uv_tty_t* handle) { if (handle->flags & UV_HANDLE_TTY_RAW) { - uv_tty_queue_read_raw(loop, handle); + uv__tty_queue_read_raw(loop, handle); } else { - uv_tty_queue_read_line(loop, handle); + uv__tty_queue_read_line(loop, handle); } } @@ -947,7 +947,7 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, /* Wait for more input events. */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_tty_queue_read(loop, handle); + uv__tty_queue_read(loop, handle); } DECREASE_PENDING_REQ_COUNT(handle); @@ -992,14 +992,14 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle, /* Wait for more input events. */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_tty_queue_read(loop, handle); + uv__tty_queue_read(loop, handle); } DECREASE_PENDING_REQ_COUNT(handle); } -void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, +void uv__process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* req) { assert(handle->type == UV_TTY); assert(handle->flags & UV_HANDLE_TTY_READABLE); @@ -1015,7 +1015,7 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, } -int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, +int uv__tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb) { uv_loop_t* loop = handle->loop; @@ -1038,20 +1038,20 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, * Short-circuit if this could be the case. */ if (handle->tty.rd.last_key_len > 0) { SET_REQ_SUCCESS(&handle->read_req); - uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req); + uv__insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req); /* Make sure no attempt is made to insert it again until it's handled. */ handle->flags |= UV_HANDLE_READ_PENDING; handle->reqs_pending++; return 0; } - uv_tty_queue_read(loop, handle); + uv__tty_queue_read(loop, handle); return 0; } -int uv_tty_read_stop(uv_tty_t* handle) { +int uv__tty_read_stop(uv_tty_t* handle) { INPUT_RECORD record; DWORD written, err; @@ -1137,7 +1137,7 @@ static int uv__cancel_read_console(uv_tty_t* handle) { } -static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) { +static void uv__tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) { uv_tty_virtual_width = info->dwSize.X; uv_tty_virtual_height = info->srWindow.Bottom - info->srWindow.Top + 1; @@ -1160,12 +1160,12 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) { } -static COORD uv_tty_make_real_coord(uv_tty_t* handle, +static COORD uv__tty_make_real_coord(uv_tty_t* handle, CONSOLE_SCREEN_BUFFER_INFO* info, int x, unsigned char x_relative, int y, unsigned char y_relative) { COORD result; - uv_tty_update_virtual_window(info); + uv__tty_update_virtual_window(info); /* Adjust y position */ if (y_relative) { @@ -1197,7 +1197,7 @@ static COORD uv_tty_make_real_coord(uv_tty_t* handle, } -static int uv_tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length, +static int uv__tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length, DWORD* error) { DWORD written; @@ -1218,7 +1218,7 @@ static int uv_tty_emit_text(uv_tty_t* handle, WCHAR buffer[], DWORD length, } -static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative, +static int uv__tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative, int y, unsigned char y_relative, DWORD* error) { CONSOLE_SCREEN_BUFFER_INFO info; COORD pos; @@ -1232,7 +1232,7 @@ static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative, *error = GetLastError(); } - pos = uv_tty_make_real_coord(handle, &info, x, x_relative, y, y_relative); + pos = uv__tty_make_real_coord(handle, &info, x, x_relative, y, y_relative); if (!SetConsoleCursorPosition(handle->handle, pos)) { if (GetLastError() == ERROR_INVALID_PARAMETER) { @@ -1248,7 +1248,7 @@ static int uv_tty_move_caret(uv_tty_t* handle, int x, unsigned char x_relative, } -static int uv_tty_reset(uv_tty_t* handle, DWORD* error) { +static int uv__tty_reset(uv_tty_t* handle, DWORD* error) { const COORD origin = {0, 0}; const WORD char_attrs = uv_tty_default_text_attributes; CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; @@ -1300,7 +1300,7 @@ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) { /* Move the virtual window up to the top. */ uv_tty_virtual_offset = 0; - uv_tty_update_virtual_window(&screen_buffer_info); + uv__tty_update_virtual_window(&screen_buffer_info); /* Reset the cursor size and the cursor state. */ if (!SetConsoleCursorInfo(handle->handle, &uv_tty_default_cursor_info)) { @@ -1312,7 +1312,7 @@ static int uv_tty_reset(uv_tty_t* handle, DWORD* error) { } -static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, +static int uv__tty_clear(uv_tty_t* handle, int dir, char entire_screen, DWORD* error) { CONSOLE_SCREEN_BUFFER_INFO info; COORD start, end; @@ -1341,7 +1341,7 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, x2r = 1; } else { /* Clear to end of row. We pretend the console is 65536 characters wide, - * uv_tty_make_real_coord will clip it to the actual console width. */ + * uv__tty_make_real_coord will clip it to the actual console width. */ x2 = 0xffff; x2r = 0; } @@ -1364,8 +1364,8 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, return -1; } - start = uv_tty_make_real_coord(handle, &info, x1, x1r, y1, y1r); - end = uv_tty_make_real_coord(handle, &info, x2, x2r, y2, y2r); + start = uv__tty_make_real_coord(handle, &info, x1, x1r, y1, y1r); + end = uv__tty_make_real_coord(handle, &info, x2, x2r, y2, y2r); count = (end.Y * info.dwSize.X + end.X) - (start.Y * info.dwSize.X + start.X) + 1; @@ -1400,7 +1400,7 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, info.wAttributes |= bg >> 4; \ } while (0) -static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { +static int uv__tty_set_style(uv_tty_t* handle, DWORD* error) { unsigned short argc = handle->tty.wr.ansi_csi_argc; unsigned short* argv = handle->tty.wr.ansi_csi_argv; int i; @@ -1556,7 +1556,7 @@ static int uv_tty_set_style(uv_tty_t* handle, DWORD* error) { } -static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes, +static int uv__tty_save_state(uv_tty_t* handle, unsigned char save_attributes, DWORD* error) { CONSOLE_SCREEN_BUFFER_INFO info; @@ -1569,10 +1569,11 @@ static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes, return -1; } - uv_tty_update_virtual_window(&info); + uv__tty_update_virtual_window(&info); handle->tty.wr.saved_position.X = info.dwCursorPosition.X; - handle->tty.wr.saved_position.Y = info.dwCursorPosition.Y - uv_tty_virtual_offset; + handle->tty.wr.saved_position.Y = info.dwCursorPosition.Y - + uv_tty_virtual_offset; handle->flags |= UV_HANDLE_TTY_SAVED_POSITION; if (save_attributes) { @@ -1585,7 +1586,7 @@ static int uv_tty_save_state(uv_tty_t* handle, unsigned char save_attributes, } -static int uv_tty_restore_state(uv_tty_t* handle, +static int uv__tty_restore_state(uv_tty_t* handle, unsigned char restore_attributes, DWORD* error) { CONSOLE_SCREEN_BUFFER_INFO info; WORD new_attributes; @@ -1595,7 +1596,7 @@ static int uv_tty_restore_state(uv_tty_t* handle, } if (handle->flags & UV_HANDLE_TTY_SAVED_POSITION) { - if (uv_tty_move_caret(handle, + if (uv__tty_move_caret(handle, handle->tty.wr.saved_position.X, 0, handle->tty.wr.saved_position.Y, @@ -1625,7 +1626,7 @@ static int uv_tty_restore_state(uv_tty_t* handle, return 0; } -static int uv_tty_set_cursor_visibility(uv_tty_t* handle, +static int uv__tty_set_cursor_visibility(uv_tty_t* handle, BOOL visible, DWORD* error) { CONSOLE_CURSOR_INFO cursor_info; @@ -1645,7 +1646,7 @@ static int uv_tty_set_cursor_visibility(uv_tty_t* handle, return 0; } -static int uv_tty_set_cursor_shape(uv_tty_t* handle, int style, DWORD* error) { +static int uv__tty_set_cursor_shape(uv_tty_t* handle, int style, DWORD* error) { CONSOLE_CURSOR_INFO cursor_info; if (!GetConsoleCursorInfo(handle->handle, &cursor_info)) { @@ -1670,7 +1671,7 @@ static int uv_tty_set_cursor_shape(uv_tty_t* handle, int style, DWORD* error) { } -static int uv_tty_write_bufs(uv_tty_t* handle, +static int uv__tty_write_bufs(uv_tty_t* handle, const uv_buf_t bufs[], unsigned int nbufs, DWORD* error) { @@ -1683,7 +1684,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, #define FLUSH_TEXT() \ do { \ if (utf16_buf_used > 0) { \ - uv_tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \ + uv__tty_emit_text(handle, utf16_buf, utf16_buf_used, error); \ utf16_buf_used = 0; \ } \ } while (0) @@ -1802,21 +1803,21 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case 'c': /* Full console reset. */ FLUSH_TEXT(); - uv_tty_reset(handle, error); + uv__tty_reset(handle, error); ansi_parser_state = ANSI_NORMAL; continue; case '7': /* Save the cursor position and text attributes. */ FLUSH_TEXT(); - uv_tty_save_state(handle, 1, error); + uv__tty_save_state(handle, 1, error); ansi_parser_state = ANSI_NORMAL; continue; case '8': /* Restore the cursor position and text attributes */ FLUSH_TEXT(); - uv_tty_restore_state(handle, 1, error); + uv__tty_restore_state(handle, 1, error); ansi_parser_state = ANSI_NORMAL; continue; @@ -1849,7 +1850,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, ? handle->tty.wr.ansi_csi_argv[0] : 1; if (style >= 0 && style <= 6) { FLUSH_TEXT(); - uv_tty_set_cursor_shape(handle, style, error); + uv__tty_set_cursor_shape(handle, style, error); } } @@ -1947,7 +1948,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, if (handle->tty.wr.ansi_csi_argc == 1 && handle->tty.wr.ansi_csi_argv[0] == 25) { FLUSH_TEXT(); - uv_tty_set_cursor_visibility(handle, 0, error); + uv__tty_set_cursor_visibility(handle, 0, error); } break; @@ -1956,7 +1957,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, if (handle->tty.wr.ansi_csi_argc == 1 && handle->tty.wr.ansi_csi_argv[0] == 25) { FLUSH_TEXT(); - uv_tty_set_cursor_visibility(handle, 1, error); + uv__tty_set_cursor_visibility(handle, 1, error); } break; } @@ -1970,7 +1971,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, FLUSH_TEXT(); y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); - uv_tty_move_caret(handle, 0, 1, y, 1, error); + uv__tty_move_caret(handle, 0, 1, y, 1, error); break; case 'B': @@ -1978,7 +1979,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, FLUSH_TEXT(); y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; - uv_tty_move_caret(handle, 0, 1, y, 1, error); + uv__tty_move_caret(handle, 0, 1, y, 1, error); break; case 'C': @@ -1986,7 +1987,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, FLUSH_TEXT(); x = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; - uv_tty_move_caret(handle, x, 1, 0, 1, error); + uv__tty_move_caret(handle, x, 1, 0, 1, error); break; case 'D': @@ -1994,7 +1995,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, FLUSH_TEXT(); x = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); - uv_tty_move_caret(handle, x, 1, 0, 1, error); + uv__tty_move_caret(handle, x, 1, 0, 1, error); break; case 'E': @@ -2002,7 +2003,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, FLUSH_TEXT(); y = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1; - uv_tty_move_caret(handle, 0, 0, y, 1, error); + uv__tty_move_caret(handle, 0, 0, y, 1, error); break; case 'F': @@ -2010,7 +2011,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, FLUSH_TEXT(); y = -(handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 1); - uv_tty_move_caret(handle, 0, 0, y, 1, error); + uv__tty_move_caret(handle, 0, 0, y, 1, error); break; case 'G': @@ -2019,7 +2020,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, x = (handle->tty.wr.ansi_csi_argc >= 1 && handle->tty.wr.ansi_csi_argv[0]) ? handle->tty.wr.ansi_csi_argv[0] - 1 : 0; - uv_tty_move_caret(handle, x, 0, 0, 1, error); + uv__tty_move_caret(handle, x, 0, 0, 1, error); break; case 'H': @@ -2032,7 +2033,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, x = (handle->tty.wr.ansi_csi_argc >= 2 && handle->tty.wr.ansi_csi_argv[1]) ? handle->tty.wr.ansi_csi_argv[1] - 1 : 0; - uv_tty_move_caret(handle, x, 0, y, 0, error); + uv__tty_move_caret(handle, x, 0, y, 0, error); break; case 'J': @@ -2041,7 +2042,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0; if (d >= 0 && d <= 2) { - uv_tty_clear(handle, d, 1, error); + uv__tty_clear(handle, d, 1, error); } break; @@ -2051,26 +2052,26 @@ static int uv_tty_write_bufs(uv_tty_t* handle, d = handle->tty.wr.ansi_csi_argc ? handle->tty.wr.ansi_csi_argv[0] : 0; if (d >= 0 && d <= 2) { - uv_tty_clear(handle, d, 0, error); + uv__tty_clear(handle, d, 0, error); } break; case 'm': /* Set style */ FLUSH_TEXT(); - uv_tty_set_style(handle, error); + uv__tty_set_style(handle, error); break; case 's': /* Save the cursor position. */ FLUSH_TEXT(); - uv_tty_save_state(handle, 0, error); + uv__tty_save_state(handle, 0, error); break; case 'u': /* Restore the cursor position */ FLUSH_TEXT(); - uv_tty_restore_state(handle, 0, error); + uv__tty_restore_state(handle, 0, error); break; } } @@ -2179,7 +2180,7 @@ static int uv_tty_write_bufs(uv_tty_t* handle, } -int uv_tty_write(uv_loop_t* loop, +int uv__tty_write(uv_loop_t* loop, uv_write_t* req, uv_tty_t* handle, const uv_buf_t bufs[], @@ -2197,13 +2198,13 @@ int uv_tty_write(uv_loop_t* loop, req->u.io.queued_bytes = 0; - if (!uv_tty_write_bufs(handle, bufs, nbufs, &error)) { + if (!uv__tty_write_bufs(handle, bufs, nbufs, &error)) { SET_REQ_SUCCESS(req); } else { SET_REQ_ERROR(req, error); } - uv_insert_pending_req(loop, (uv_req_t*) req); + uv__insert_pending_req(loop, (uv_req_t*) req); return 0; } @@ -2217,14 +2218,14 @@ int uv__tty_try_write(uv_tty_t* handle, if (handle->stream.conn.write_reqs_pending > 0) return UV_EAGAIN; - if (uv_tty_write_bufs(handle, bufs, nbufs, &error)) + if (uv__tty_write_bufs(handle, bufs, nbufs, &error)) return uv_translate_sys_error(error); return uv__count_bufs(bufs, nbufs); } -void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, +void uv__process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, uv_write_t* req) { int err; @@ -2236,20 +2237,22 @@ void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, req->cb(req, uv_translate_sys_error(err)); } + handle->stream.conn.write_reqs_pending--; - if (handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*)handle); - } + if (handle->stream.conn.write_reqs_pending == 0) + if (handle->flags & UV_HANDLE_SHUTTING) + uv__process_tty_shutdown_req(loop, + handle, + handle->stream.conn.shutdown_req); DECREASE_PENDING_REQ_COUNT(handle); } -void uv_tty_close(uv_tty_t* handle) { +void uv__tty_close(uv_tty_t* handle) { assert(handle->u.fd == -1 || handle->u.fd > 2); if (handle->flags & UV_HANDLE_READING) - uv_tty_read_stop(handle); + uv__tty_read_stop(handle); if (handle->u.fd == -1) CloseHandle(handle->handle); @@ -2261,61 +2264,61 @@ void uv_tty_close(uv_tty_t* handle) { handle->flags &= ~(UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); uv__handle_closing(handle); - if (handle->reqs_pending == 0) { - uv_want_endgame(handle->loop, (uv_handle_t*) handle); - } + if (handle->reqs_pending == 0) + uv__want_endgame(handle->loop, (uv_handle_t*) handle); } -void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { - if (!(handle->flags & UV_HANDLE_TTY_READABLE) && - handle->stream.conn.shutdown_req != NULL && - handle->stream.conn.write_reqs_pending == 0) { - UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req); +void uv__process_tty_shutdown_req(uv_loop_t* loop, uv_tty_t* stream, uv_shutdown_t* req) { + assert(stream->stream.conn.write_reqs_pending == 0); + assert(req); - /* TTY shutdown is really just a no-op */ - if (handle->stream.conn.shutdown_req->cb) { - if (handle->flags & UV_HANDLE_CLOSING) { - handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED); - } else { - handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0); - } + stream->stream.conn.shutdown_req = NULL; + stream->flags &= ~UV_HANDLE_SHUTTING; + UNREGISTER_HANDLE_REQ(loop, stream, req); + + /* TTY shutdown is really just a no-op */ + if (req->cb) { + if (stream->flags & UV_HANDLE_CLOSING) { + req->cb(req, UV_ECANCELED); + } else { + req->cb(req, 0); } + } - handle->stream.conn.shutdown_req = NULL; + DECREASE_PENDING_REQ_COUNT(stream); +} - DECREASE_PENDING_REQ_COUNT(handle); - return; - } - if (handle->flags & UV_HANDLE_CLOSING && - handle->reqs_pending == 0) { - /* The wait handle used for raw reading should be unregistered when the - * wait callback runs. */ - assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || - handle->tty.rd.read_raw_wait == NULL); +void uv__tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { + assert(handle->flags & UV_HANDLE_CLOSING); + assert(handle->reqs_pending == 0); - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } + /* The wait handle used for raw reading should be unregistered when the + * wait callback runs. */ + assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || + handle->tty.rd.read_raw_wait == NULL); + + assert(!(handle->flags & UV_HANDLE_CLOSED)); + uv__handle_close(handle); } /* - * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working + * uv__process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working * TODO: find a way to remove it */ -void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, +void uv__process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* raw_req) { abort(); } /* - * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working + * uv__process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working * TODO: find a way to remove it */ -void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, +void uv__process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, uv_connect_t* req) { abort(); } diff --git a/Utilities/cmlibuv/src/win/udp.c b/Utilities/cmlibuv/src/win/udp.c index 7b5efa2..eaebc1e 100644 --- a/Utilities/cmlibuv/src/win/udp.c +++ b/Utilities/cmlibuv/src/win/udp.c @@ -60,7 +60,7 @@ int uv_udp_getsockname(const uv_udp_t* handle, } -static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, +static int uv__udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, int family) { DWORD yes = 1; WSAPROTOCOL_INFOW info; @@ -106,8 +106,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; - handle->func_wsarecv = uv_wsarecv_workaround; - handle->func_wsarecvfrom = uv_wsarecvfrom_workaround; + handle->func_wsarecv = uv__wsarecv_workaround; + handle->func_wsarecvfrom = uv__wsarecvfrom_workaround; } else if (GetLastError() != ERROR_INVALID_FUNCTION) { return GetLastError(); } @@ -155,7 +155,7 @@ int uv__udp_init_ex(uv_loop_t* loop, return uv_translate_sys_error(err); } - err = uv_udp_set_socket(handle->loop, handle, sock, domain); + err = uv__udp_set_socket(handle->loop, handle, sock, domain); if (err) { closesocket(sock); QUEUE_REMOVE(&handle->handle_queue); @@ -167,7 +167,7 @@ int uv__udp_init_ex(uv_loop_t* loop, } -void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) { +void uv__udp_close(uv_loop_t* loop, uv_udp_t* handle) { uv_udp_recv_stop(handle); closesocket(handle->socket); handle->socket = INVALID_SOCKET; @@ -175,12 +175,12 @@ void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) { uv__handle_closing(handle); if (handle->reqs_pending == 0) { - uv_want_endgame(loop, (uv_handle_t*) handle); + uv__want_endgame(loop, (uv_handle_t*) handle); } } -void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { +void uv__udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); @@ -194,10 +194,10 @@ int uv_udp_using_recvmmsg(const uv_udp_t* handle) { } -static int uv_udp_maybe_bind(uv_udp_t* handle, - const struct sockaddr* addr, - unsigned int addrlen, - unsigned int flags) { +static int uv__udp_maybe_bind(uv_udp_t* handle, + const struct sockaddr* addr, + unsigned int addrlen, + unsigned int flags) { int r; int err; DWORD no = 0; @@ -216,7 +216,7 @@ static int uv_udp_maybe_bind(uv_udp_t* handle, return WSAGetLastError(); } - err = uv_udp_set_socket(handle->loop, handle, sock, addr->sa_family); + err = uv__udp_set_socket(handle->loop, handle, sock, addr->sa_family); if (err) { closesocket(sock); return err; @@ -264,7 +264,7 @@ static int uv_udp_maybe_bind(uv_udp_t* handle, } -static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { +static void uv__udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { uv_req_t* req; uv_buf_t buf; DWORD bytes, flags; @@ -311,7 +311,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { handle->flags |= UV_HANDLE_READ_PENDING; req->u.io.overlapped.InternalHigh = bytes; handle->reqs_pending++; - uv_insert_pending_req(loop, req); + uv__insert_pending_req(loop, req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* The req will be processed with IOCP. */ handle->flags |= UV_HANDLE_READ_PENDING; @@ -319,7 +319,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { } else { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, req); + uv__insert_pending_req(loop, req); handle->reqs_pending++; } @@ -343,7 +343,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { handle->flags |= UV_HANDLE_READ_PENDING; req->u.io.overlapped.InternalHigh = bytes; handle->reqs_pending++; - uv_insert_pending_req(loop, req); + uv__insert_pending_req(loop, req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* The req will be processed with IOCP. */ handle->flags |= UV_HANDLE_READ_PENDING; @@ -351,7 +351,7 @@ static void uv_udp_queue_recv(uv_loop_t* loop, uv_udp_t* handle) { } else { /* Make this req pending reporting an error. */ SET_REQ_ERROR(req, WSAGetLastError()); - uv_insert_pending_req(loop, req); + uv__insert_pending_req(loop, req); handle->reqs_pending++; } } @@ -367,10 +367,10 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, return UV_EALREADY; } - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - 0); + err = uv__udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip4_any_, + sizeof(uv_addr_ip4_any_), + 0); if (err) return uv_translate_sys_error(err); @@ -384,7 +384,7 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, /* If reading was stopped and then started again, there could still be a recv * request pending. */ if (!(handle->flags & UV_HANDLE_READ_PENDING)) - uv_udp_queue_recv(loop, handle); + uv__udp_queue_recv(loop, handle); return 0; } @@ -433,7 +433,7 @@ static int uv__send(uv_udp_send_t* req, handle->send_queue_size += req->u.io.queued_bytes; handle->send_queue_count++; REGISTER_HANDLE_REQ(loop, handle, req); - uv_insert_pending_req(loop, (uv_req_t*)req); + uv__insert_pending_req(loop, (uv_req_t*)req); } else if (UV_SUCCEEDED_WITH_IOCP(result == 0)) { /* Request queued by the kernel. */ req->u.io.queued_bytes = uv__count_bufs(bufs, nbufs); @@ -450,7 +450,7 @@ static int uv__send(uv_udp_send_t* req, } -void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, +void uv__process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, uv_req_t* req) { uv_buf_t buf; int partial; @@ -554,14 +554,14 @@ done: /* Post another read if still reading and not closing. */ if ((handle->flags & UV_HANDLE_READING) && !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_udp_queue_recv(loop, handle); + uv__udp_queue_recv(loop, handle); } DECREASE_PENDING_REQ_COUNT(handle); } -void uv_process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, +void uv__process_udp_send_req(uv_loop_t* loop, uv_udp_t* handle, uv_udp_send_t* req) { int err; @@ -598,10 +598,10 @@ static int uv__udp_set_membership4(uv_udp_t* handle, return UV_EINVAL; /* If the socket is unbound, bind to inaddr_any. */ - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - UV_UDP_REUSEADDR); + err = uv__udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip4_any_, + sizeof(uv_addr_ip4_any_), + UV_UDP_REUSEADDR); if (err) return uv_translate_sys_error(err); @@ -652,10 +652,10 @@ int uv__udp_set_membership6(uv_udp_t* handle, if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6)) return UV_EINVAL; - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip6_any_, - sizeof(uv_addr_ip6_any_), - UV_UDP_REUSEADDR); + err = uv__udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip6_any_, + sizeof(uv_addr_ip6_any_), + UV_UDP_REUSEADDR); if (err) return uv_translate_sys_error(err); @@ -708,10 +708,10 @@ static int uv__udp_set_source_membership4(uv_udp_t* handle, return UV_EINVAL; /* If the socket is unbound, bind to inaddr_any. */ - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip4_any_, - sizeof(uv_addr_ip4_any_), - UV_UDP_REUSEADDR); + err = uv__udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip4_any_, + sizeof(uv_addr_ip4_any_), + UV_UDP_REUSEADDR); if (err) return uv_translate_sys_error(err); @@ -763,10 +763,10 @@ int uv__udp_set_source_membership6(uv_udp_t* handle, if ((handle->flags & UV_HANDLE_BOUND) && !(handle->flags & UV_HANDLE_IPV6)) return UV_EINVAL; - err = uv_udp_maybe_bind(handle, - (const struct sockaddr*) &uv_addr_ip6_any_, - sizeof(uv_addr_ip6_any_), - UV_UDP_REUSEADDR); + err = uv__udp_maybe_bind(handle, + (const struct sockaddr*) &uv_addr_ip6_any_, + sizeof(uv_addr_ip6_any_), + UV_UDP_REUSEADDR); if (err) return uv_translate_sys_error(err); @@ -962,10 +962,10 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { return uv_translate_sys_error(GetLastError()); } - err = uv_udp_set_socket(handle->loop, - handle, - sock, - protocol_info.iAddressFamily); + err = uv__udp_set_socket(handle->loop, + handle, + sock, + protocol_info.iAddressFamily); if (err) return uv_translate_sys_error(err); @@ -1044,7 +1044,7 @@ int uv__udp_bind(uv_udp_t* handle, unsigned int flags) { int err; - err = uv_udp_maybe_bind(handle, addr, addrlen, flags); + err = uv__udp_maybe_bind(handle, addr, addrlen, flags); if (err) return uv_translate_sys_error(err); @@ -1066,7 +1066,7 @@ int uv__udp_connect(uv_udp_t* handle, else return UV_EINVAL; - err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0); + err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0); if (err) return uv_translate_sys_error(err); } @@ -1117,7 +1117,7 @@ int uv__udp_send(uv_udp_send_t* req, else return UV_EINVAL; - err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0); + err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0); if (err) return uv_translate_sys_error(err); } @@ -1146,6 +1146,7 @@ int uv__udp_try_send(uv_udp_t* handle, err = uv__convert_to_localhost_if_unspecified(addr, &converted); if (err) return err; + addr = (const struct sockaddr*) &converted; } /* Already sending a message.*/ @@ -1159,7 +1160,7 @@ int uv__udp_try_send(uv_udp_t* handle, bind_addr = (const struct sockaddr*) &uv_addr_ip6_any_; else return UV_EINVAL; - err = uv_udp_maybe_bind(handle, bind_addr, addrlen, 0); + err = uv__udp_maybe_bind(handle, bind_addr, addrlen, 0); if (err) return uv_translate_sys_error(err); } @@ -1169,7 +1170,7 @@ int uv__udp_try_send(uv_udp_t* handle, nbufs, &bytes, 0, - (const struct sockaddr*) &converted, + addr, addrlen, NULL, NULL); diff --git a/Utilities/cmlibuv/src/win/util.c b/Utilities/cmlibuv/src/win/util.c index 33e874a..9943205 100644 --- a/Utilities/cmlibuv/src/win/util.c +++ b/Utilities/cmlibuv/src/win/util.c @@ -531,103 +531,25 @@ int uv_resident_set_memory(size_t* rss) { int uv_uptime(double* uptime) { - BYTE stack_buffer[4096]; - BYTE* malloced_buffer = NULL; - BYTE* buffer = (BYTE*) stack_buffer; - size_t buffer_size = sizeof(stack_buffer); - DWORD data_size; - - PERF_DATA_BLOCK* data_block; - PERF_OBJECT_TYPE* object_type; - PERF_COUNTER_DEFINITION* counter_definition; - - DWORD i; - - for (;;) { - LONG result; - - data_size = (DWORD) buffer_size; - result = RegQueryValueExW(HKEY_PERFORMANCE_DATA, - L"2", - NULL, - NULL, - buffer, - &data_size); - if (result == ERROR_SUCCESS) { - break; - } else if (result != ERROR_MORE_DATA) { - *uptime = 0; - return uv_translate_sys_error(result); - } - - buffer_size *= 2; - /* Don't let the buffer grow infinitely. */ - if (buffer_size > 1 << 20) { - goto internalError; - } - - uv__free(malloced_buffer); - - buffer = malloced_buffer = (BYTE*) uv__malloc(buffer_size); - if (malloced_buffer == NULL) { - *uptime = 0; - return UV_ENOMEM; - } - } - - if (data_size < sizeof(*data_block)) - goto internalError; - - data_block = (PERF_DATA_BLOCK*) buffer; - - if (wmemcmp(data_block->Signature, L"PERF", 4) != 0) - goto internalError; - - if (data_size < data_block->HeaderLength + sizeof(*object_type)) - goto internalError; - - object_type = (PERF_OBJECT_TYPE*) (buffer + data_block->HeaderLength); - - if (object_type->NumInstances != PERF_NO_INSTANCES) - goto internalError; + *uptime = GetTickCount64() / 1000.0; + return 0; +} - counter_definition = (PERF_COUNTER_DEFINITION*) (buffer + - data_block->HeaderLength + object_type->HeaderLength); - for (i = 0; i < object_type->NumCounters; i++) { - if ((BYTE*) counter_definition + sizeof(*counter_definition) > - buffer + data_size) { - break; - } - if (counter_definition->CounterNameTitleIndex == 674 && - counter_definition->CounterSize == sizeof(uint64_t)) { - if (counter_definition->CounterOffset + sizeof(uint64_t) > data_size || - !(counter_definition->CounterType & PERF_OBJECT_TIMER)) { - goto internalError; - } else { - BYTE* address = (BYTE*) object_type + object_type->DefinitionLength + - counter_definition->CounterOffset; - uint64_t value = *((uint64_t*) address); - *uptime = floor((double) (object_type->PerfTime.QuadPart - value) / - (double) object_type->PerfFreq.QuadPart); - uv__free(malloced_buffer); - return 0; - } - } +unsigned int uv_available_parallelism(void) { + SYSTEM_INFO info; + unsigned rc; - counter_definition = (PERF_COUNTER_DEFINITION*) - ((BYTE*) counter_definition + counter_definition->ByteLength); - } + /* TODO(bnoordhuis) Use GetLogicalProcessorInformationEx() to support systems + * with > 64 CPUs? See https://github.com/libuv/libuv/pull/3458 + */ + GetSystemInfo(&info); - /* If we get here, the uptime value was not found. */ - uv__free(malloced_buffer); - *uptime = 0; - return UV_ENOSYS; + rc = info.dwNumberOfProcessors; + if (rc < 1) + rc = 1; - internalError: - uv__free(malloced_buffer); - *uptime = 0; - return UV_EIO; + return rc; } diff --git a/Utilities/cmlibuv/src/win/winapi.c b/Utilities/cmlibuv/src/win/winapi.c index bf306cd..53147b8 100644 --- a/Utilities/cmlibuv/src/win/winapi.c +++ b/Utilities/cmlibuv/src/win/winapi.c @@ -48,7 +48,7 @@ sSetWinEventHook pSetWinEventHook; /* ws2_32.dll function pointer */ uv_sGetHostNameW pGetHostNameW; -void uv_winapi_init(void) { +void uv__winapi_init(void) { HMODULE ntdll_module; HMODULE powrprof_module; HMODULE user32_module; @@ -126,19 +126,19 @@ void uv_winapi_init(void) { kernel32_module, "GetQueuedCompletionStatusEx"); - powrprof_module = LoadLibraryA("powrprof.dll"); + powrprof_module = LoadLibraryExA("powrprof.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); if (powrprof_module != NULL) { pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification) GetProcAddress(powrprof_module, "PowerRegisterSuspendResumeNotification"); } - user32_module = LoadLibraryA("user32.dll"); + user32_module = GetModuleHandleA("user32.dll"); if (user32_module != NULL) { pSetWinEventHook = (sSetWinEventHook) GetProcAddress(user32_module, "SetWinEventHook"); } - ws2_32_module = LoadLibraryA("ws2_32.dll"); + ws2_32_module = GetModuleHandleA("ws2_32.dll"); if (ws2_32_module != NULL) { pGetHostNameW = (uv_sGetHostNameW) GetProcAddress( ws2_32_module, diff --git a/Utilities/cmlibuv/src/win/winsock.c b/Utilities/cmlibuv/src/win/winsock.c index 4cf6e6b..a68b095 100644 --- a/Utilities/cmlibuv/src/win/winsock.c +++ b/Utilities/cmlibuv/src/win/winsock.c @@ -38,7 +38,7 @@ struct sockaddr_in6 uv_addr_ip6_any_; /* * Retrieves the pointer to a winsock extension function. */ -static BOOL uv_get_extension_function(SOCKET socket, GUID guid, +static BOOL uv__get_extension_function(SOCKET socket, GUID guid, void **target) { int result; DWORD bytes; @@ -62,20 +62,20 @@ static BOOL uv_get_extension_function(SOCKET socket, GUID guid, } -BOOL uv_get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target) { +BOOL uv__get_acceptex_function(SOCKET socket, LPFN_ACCEPTEX* target) { const GUID wsaid_acceptex = WSAID_ACCEPTEX; - return uv_get_extension_function(socket, wsaid_acceptex, (void**)target); + return uv__get_extension_function(socket, wsaid_acceptex, (void**)target); } -BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) { +BOOL uv__get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) { const GUID wsaid_connectex = WSAID_CONNECTEX; - return uv_get_extension_function(socket, wsaid_connectex, (void**)target); + return uv__get_extension_function(socket, wsaid_connectex, (void**)target); } -void uv_winsock_init(void) { +void uv__winsock_init(void) { WSADATA wsa_data; int errorno; SOCKET dummy; @@ -134,7 +134,7 @@ void uv_winsock_init(void) { } -int uv_ntstatus_to_winsock_error(NTSTATUS status) { +int uv__ntstatus_to_winsock_error(NTSTATUS status) { switch (status) { case STATUS_SUCCESS: return ERROR_SUCCESS; @@ -267,7 +267,7 @@ int uv_ntstatus_to_winsock_error(NTSTATUS status) { * the user to use the default msafd driver, doesn't work when other LSPs are * stacked on top of it. */ -int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers, +int WSAAPI uv__wsarecv_workaround(SOCKET socket, WSABUF* buffers, DWORD buffer_count, DWORD* bytes, DWORD* flags, WSAOVERLAPPED *overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) { NTSTATUS status; @@ -346,7 +346,7 @@ int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers, break; default: - error = uv_ntstatus_to_winsock_error(status); + error = uv__ntstatus_to_winsock_error(status); break; } @@ -360,8 +360,8 @@ int WSAAPI uv_wsarecv_workaround(SOCKET socket, WSABUF* buffers, } -/* See description of uv_wsarecv_workaround. */ -int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, +/* See description of uv__wsarecv_workaround. */ +int WSAAPI uv__wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, DWORD buffer_count, DWORD* bytes, DWORD* flags, struct sockaddr* addr, int* addr_len, WSAOVERLAPPED *overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_routine) { @@ -444,7 +444,7 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, break; default: - error = uv_ntstatus_to_winsock_error(status); + error = uv__ntstatus_to_winsock_error(status); break; } @@ -458,7 +458,7 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, } -int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, +int WSAAPI uv__msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, AFD_POLL_INFO* info_out, OVERLAPPED* overlapped) { IO_STATUS_BLOCK iosb; IO_STATUS_BLOCK* iosb_ptr; @@ -531,7 +531,7 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, break; default: - error = uv_ntstatus_to_winsock_error(status); + error = uv__ntstatus_to_winsock_error(status); break; } diff --git a/Utilities/std/cmext/enum_set b/Utilities/std/cmext/enum_set index 4225b82..d7b8b39 100644 --- a/Utilities/std/cmext/enum_set +++ b/Utilities/std/cmext/enum_set @@ -146,6 +146,7 @@ public: { this->Set.reset(); this->insert(list); + return *this; } // Iterators @@ -298,17 +299,15 @@ public: { if (this->contains(e)) { return iterator(this, static_cast<size_type>(e)); - } else { - return this->end(); } + return this->end(); } const_iterator find(key_type e) const { if (this->contains(e)) { return const_iterator(this, static_cast<size_type>(e)); - } else { - return this->end(); } + return this->end(); } bool contains(key_type e) const @@ -317,6 +316,10 @@ public: } private: + template <typename E> + friend inline bool operator==(const enum_set<E>& lhs, + const enum_set<E>& rhs) noexcept; + template <typename E, typename Predicate> friend inline void erase_if(enum_set<E>& set, Predicate pred); @@ -369,7 +372,7 @@ template <typename Enum> inline bool operator==(const enum_set<Enum>& lhs, const enum_set<Enum>& rhs) noexcept { - return lhs == rhs; + return lhs.Set == rhs.Set; } template <typename Enum> @@ -281,6 +281,7 @@ CMAKE_UNUSED_SOURCES="\ " CMAKE_CXX_SOURCES="\ + cmAddCompileDefinitionsCommand \ cmAddCustomCommandCommand \ cmAddCustomTargetCommand \ cmAddDefinitionsCommand \ @@ -301,6 +302,7 @@ CMAKE_CXX_SOURCES="\ cmBinUtilsWindowsPEDumpbinGetRuntimeDependenciesTool \ cmBinUtilsWindowsPELinker \ cmBinUtilsWindowsPEObjdumpGetRuntimeDependenciesTool \ + cmBlockCommand \ cmBreakCommand \ cmBuildCommand \ cmCMakeLanguageCommand \ @@ -328,6 +330,7 @@ CMAKE_CXX_SOURCES="\ cmCustomCommand \ cmCustomCommandGenerator \ cmCustomCommandLines \ + cmCxxModuleMapper \ cmDefinePropertyCommand \ cmDefinitions \ cmDocumentationFormatter \ @@ -337,6 +340,7 @@ CMAKE_CXX_SOURCES="\ cmExecProgramCommand \ cmExecuteProcessCommand \ cmExpandedCommandArgument \ + cmExperimental \ cmExportBuildFileGenerator \ cmExportFileGenerator \ cmExportInstallFileGenerator \ @@ -391,6 +395,7 @@ CMAKE_CXX_SOURCES="\ cmIncludeRegularExpressionCommand \ cmInstallCommand \ cmInstallCommandArguments \ + cmInstallCxxModuleBmiGenerator \ cmInstallDirectoryGenerator \ cmInstallExportGenerator \ cmInstallFileSetGenerator \ @@ -588,6 +593,7 @@ if ${cmake_system_mingw}; then src/inet.c \ src/threadpool.c \ src/strscpy.c \ + src/strtok.c \ src/timer.c \ src/uv-common.c \ src/win/async.c \ @@ -618,6 +624,7 @@ if ${cmake_system_mingw}; then else LIBUV_C_SOURCES="\ src/strscpy.c \ + src/strtok.c \ src/timer.c \ src/uv-common.c \ src/unix/cmake-bootstrap.c \ @@ -634,6 +641,7 @@ else src/unix/signal.c \ src/unix/stream.c \ src/unix/tcp.c \ + src/unix/tty.c \ " fi |