diff options
61 files changed, 1089 insertions, 152 deletions
diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e5e7e30 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +[{CMakeLists.txt,*.cmake,*.rst}] +indent_size = 2 +indent_style = space diff --git a/.gitattributes b/.gitattributes index 3da2d60..fac38df 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ .git* export-ignore .hooks* export-ignore +.editorconfig export-ignore # Custom attribute to mark sources as using our C code style. [attr]our-c-style whitespace=tab-in-indent format.clang-format-6.0 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 626071a..073630e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -186,6 +186,29 @@ upload:linux-x86_64-package: variables: RSYNC_DESTINATION: dev +build:linux-aarch64-package: + extends: + - .linux_package_aarch64 + - .cmake_build_linux_package + - .cmake_release_artifacts + - .linux_builder_tags_aarch64 + - .run_only_for_package + dependencies: + - prep:doc-package + needs: + - prep:doc-package + +upload:linux-aarch64-package: + extends: + - .rsync_upload + - .run_only_for_package + dependencies: + - build:linux-aarch64-package + needs: + - build:linux-aarch64-package + variables: + RSYNC_DESTINATION: dev + # macOS builds build:macos-ninja: diff --git a/.gitlab/artifacts.yml b/.gitlab/artifacts.yml index 589b16c..76ffd27 100644 --- a/.gitlab/artifacts.yml +++ b/.gitlab/artifacts.yml @@ -74,6 +74,7 @@ paths: # Any packages made. - build/cmake-*-Linux-x86_64.* + - build/cmake-*-Linux-aarch64.* - build/cmake-*-macos-universal.* # Any source packages made. - build/cmake-*.tar.gz diff --git a/.gitlab/ci/sccache.sh b/.gitlab/ci/sccache.sh index af24710..77bedaa 100755 --- a/.gitlab/ci/sccache.sh +++ b/.gitlab/ci/sccache.sh @@ -2,21 +2,30 @@ set -e -case "$( uname -s )" in - Linux) +readonly kernel="$(uname -s)-$(uname -m)" +case $kernel in + Linux-x86_64) version="0.2.13" shatool="sha256sum" sha256sum="28a5499e340865b08b632306b435913beb590fbd7b49a3f887a623b459fabdeb" platform="x86_64-unknown-linux-musl" ;; - Darwin) + Linux-aarch64) + version="g6628e1f" + shatool="sha256sum" + sha256sum="bb88adbb5a29c166ecaa78d0593493b609a7f84d91d1228502a908f319b513f0" + platform="aarch64-unknown-linux-musl" + url="https://github.com/hwinit/sccache/releases/download/$version" + ;; + Darwin-x86_64) version="gfe63078" shatool="shasum -a 256" sha256sum="60a0302b1d7227f7ef56abd82266353f570d27c6e850c56c6448bf62def38888" platform="x86_64-apple-darwin" + url="https://paraview.org/files/dependencies" ;; *) - echo "Unrecognized platform $( uname -s )" + echo "Unrecognized platform $kernel" exit 1 ;; esac @@ -28,9 +37,7 @@ readonly platform readonly filename="sccache-$version-$platform" readonly tarball="$filename.tar.gz" -if [ "$( uname -s )" = "Darwin" ]; then - url="https://paraview.org/files/dependencies" -else +if [ -z "$url" ]; then url="https://github.com/mozilla/sccache/releases/download/$version" fi readonly url diff --git a/.gitlab/os-linux.yml b/.gitlab/os-linux.yml index 6684d71..a88ff6e 100644 --- a/.gitlab/os-linux.yml +++ b/.gitlab/os-linux.yml @@ -17,18 +17,21 @@ variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" -.linux_package: +.linux_package_x86_64: + image: "kitware/cmake:build-linux-x86_64-deps-2020-04-02@sha256:77e9ab183f34680990db9da5945473e288f0d6556bce79ecc1589670d656e157" + variables: GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" LAUNCHER: "scl enable devtoolset-6 rh-python36 --" + CMAKE_ARCH: x86_64 -.linux_package_x86_64: - extends: .linux_package - - image: "kitware/cmake:build-linux-x86_64-deps-2020-04-02@sha256:77e9ab183f34680990db9da5945473e288f0d6556bce79ecc1589670d656e157" +.linux_package_aarch64: + image: "kitware/cmake:build-linux-aarch64-deps-2020-12-21@sha256:0bd7dfe4e45593b04e39cd21e44011034610cfd376900558c5ef959bb1af15af" variables: - CMAKE_ARCH: x86_64 + GIT_CLONE_PATH: "$CI_BUILDS_DIR/cmake ci" + LAUNCHER: "scl enable devtoolset-7 --" + CMAKE_ARCH: aarch64 ### Debian @@ -160,6 +163,13 @@ - docker - linux +.linux_builder_tags_aarch64: + tags: + - cmake + - build + - docker + - linux-aarch64 + ## Linux-specific scripts .before_script_linux: &before_script_linux diff --git a/Auxiliary/cmake-mode.el b/Auxiliary/cmake-mode.el index 52f2d41..ddc7b40 100644 --- a/Auxiliary/cmake-mode.el +++ b/Auxiliary/cmake-mode.el @@ -211,7 +211,7 @@ the indentation. Otherwise it retains the same position on the line" "end" (or "function" "macro") (zero-or-more space) - "(" (zero-or-more (not ")")) ")")) + "(" (zero-or-more (not-char ")")) ")")) (defun cmake-beginning-of-defun () "Move backward to the beginning of a CMake function or macro. diff --git a/Copyright.txt b/Copyright.txt index b867d01..7460e73 100644 --- a/Copyright.txt +++ b/Copyright.txt @@ -1,5 +1,5 @@ CMake - Cross Platform Makefile Generator -Copyright 2000-2020 Kitware, Inc. and Contributors +Copyright 2000-2021 Kitware, Inc. and Contributors All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Help/command/add_custom_command.rst b/Help/command/add_custom_command.rst index 567af16..9a4efd1 100644 --- a/Help/command/add_custom_command.rst +++ b/Help/command/add_custom_command.rst @@ -201,6 +201,10 @@ The options are: Note that the ``IMPLICIT_DEPENDS`` option is currently supported only for Makefile generators and will be ignored by other generators. + .. note:: + + This option cannot be specified at the same time as ``DEPFILE`` option. + ``JOB_POOL`` .. versionadded:: 3.15 @@ -263,15 +267,26 @@ The options are: ``DEPFILE`` .. versionadded:: 3.7 - Specify a ``.d`` depfile for the :generator:`Ninja` generator. + Specify a ``.d`` depfile for the :generator:`Ninja` generator and + :ref:`Makefile Generators`. A ``.d`` file holds dependencies usually emitted by the custom command itself. - Using ``DEPFILE`` with other generators than Ninja is an error. + Using ``DEPFILE`` with other generators than :generator:`Ninja` or + :ref:`Makefile Generators` is an error. + + .. versionadded:: 3.20 + Added the support of :ref:`Makefile Generators`. If the ``DEPFILE`` argument is relative, it should be relative to :variable:`CMAKE_CURRENT_BINARY_DIR`, and any relative paths inside the ``DEPFILE`` should also be relative to :variable:`CMAKE_CURRENT_BINARY_DIR` - (see policy :policy:`CMP0116`.) + (see policy :policy:`CMP0116`. This policy is always ``NEW`` for + :ref:`Makefile Generators`). + + .. note:: + + For :ref:`Makefile Generators`, this option cannot be specified at the + same time as ``IMPLICIT_DEPENDS`` option. Examples: Generating Files ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/guide/tutorial/index.rst b/Help/guide/tutorial/index.rst index 4b09e53..00fa39a 100644 --- a/Help/guide/tutorial/index.rst +++ b/Help/guide/tutorial/index.rst @@ -176,7 +176,7 @@ directory: 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 ``mqsqrt.h`` header file can be found. The +an include directory so that the ``mysqrt.h`` header file can be found. The last few lines of the top-level ``CMakeLists.txt`` file should now look like: .. code-block:: cmake diff --git a/Help/release/3.19.rst b/Help/release/3.19.rst index 60a8ecc..eb49c6f 100644 --- a/Help/release/3.19.rst +++ b/Help/release/3.19.rst @@ -385,3 +385,8 @@ Changes made since CMake 3.19.0 include the following. * The :variable:`CMAKE_ISPC_HEADER_SUFFIX` variable and corresponding :prop_tgt:`ISPC_HEADER_SUFFIX` target property were added to control the header suffix used by ``ISPC`` compiler generated headers. + +3.19.3 +------ + +* A precompiled Linux ``aarch64`` binary is now provided on ``cmake.org``. diff --git a/Help/release/dev/makefile-depfile.rst b/Help/release/dev/makefile-depfile.rst new file mode 100644 index 0000000..4a3e5fb --- /dev/null +++ b/Help/release/dev/makefile-depfile.rst @@ -0,0 +1,5 @@ +makefile-depfile +---------------- + +* The :command:`add_custom_command` command gained ``DEPFILE`` support on + :ref:`Makefile Generators`. diff --git a/Modules/FetchContent.cmake b/Modules/FetchContent.cmake index 8fabcdc..ba2acfc 100644 --- a/Modules/FetchContent.cmake +++ b/Modules/FetchContent.cmake @@ -1060,7 +1060,14 @@ function(FetchContent_Populate contentName) # so no population is required. The build directory may still be specified # by the declared details though. - if(NOT EXISTS "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") + if(NOT IS_ABSOLUTE "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") + # Don't check this directory because we don't know what location it is + # expected to be relative to. We can't make this a hard error for backward + # compatibility reasons. + message(WARNING "Relative source directory specified. This is not safe, " + "as it depends on the calling directory scope.\n" + " FETCHCONTENT_SOURCE_DIR_${contentNameUpper} --> ${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") + elseif(NOT EXISTS "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") message(FATAL_ERROR "Manually specified source directory is missing:\n" " FETCHCONTENT_SOURCE_DIR_${contentNameUpper} --> ${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") endif() diff --git a/Modules/FindGTK2.cmake b/Modules/FindGTK2.cmake index 7036b66..00bfc29 100644 --- a/Modules/FindGTK2.cmake +++ b/Modules/FindGTK2.cmake @@ -805,6 +805,7 @@ foreach(_GTK2_component ${GTK2_FIND_COMPONENTS}) _GTK2_ADD_TARGET (GIOMM GTK2_DEPENDS gio glibmm gobject sigc++ glib) _GTK2_FIND_INCLUDE_DIR(ATKMM atkmm.h) + _GTK2_FIND_INCLUDE_DIR(ATKMMCONFIG atkmmconfig.h) _GTK2_FIND_LIBRARY (ATKMM atkmm true true) _GTK2_ADD_TARGET (ATKMM GTK2_DEPENDS atk glibmm gobject sigc++ glib) diff --git a/Modules/Internal/CPack/CPackNuGet.cmake b/Modules/Internal/CPack/CPackNuGet.cmake index 56bbffd..fb363f4 100644 --- a/Modules/Internal/CPack/CPackNuGet.cmake +++ b/Modules/Internal/CPack/CPackNuGet.cmake @@ -332,7 +332,7 @@ endfunction() function(_cpack_nuget_make_files_tag) set(_files) foreach(_comp IN LISTS ARGN) - string(APPEND _files " <file src=\"${_comp}\\**\" target=\".\" />\n") + string(APPEND _files " <file src=\"${_comp}/**\" target=\".\" />\n") endforeach() set(_CPACK_NUGET_FILES_TAG "<files>\n${_files} </files>" PARENT_SCOPE) endfunction() diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 49c60e6..1df2edf 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 19) -set(CMake_VERSION_PATCH 20201222) +set(CMake_VERSION_PATCH 20210104) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index ccd7255..ff2cc3e 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -296,6 +296,12 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args, status.SetError("given APPEND option with no OUTPUT."); return false; } + if (!implicit_depends.empty() && !depfile.empty() && + mf.GetGlobalGenerator()->GetName() != "Ninja") { + // Makefiles generators does not support both at the same time + status.SetError("IMPLICIT_DEPENDS and DEPFILE can not both be specified."); + return false; + } // Check for an append request. if (append) { diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx index f6e5af8..beb080f 100644 --- a/Source/cmDependsCompiler.cxx +++ b/Source/cmDependsCompiler.cxx @@ -19,6 +19,7 @@ #include "cmFileTime.h" #include "cmGccDepfileReader.h" +#include "cmGccDepfileReaderTypes.h" #include "cmGlobalUnixMakefileGenerator3.h" #include "cmLocalUnixMakefileGenerator3.h" #include "cmStringAlgorithms.h" @@ -86,7 +87,7 @@ bool cmDependsCompiler::CheckDependencies( if (!forceReadDeps) { depFileTime.Load(depFile); } - if (forceReadDeps || depFileTime.Newer(internalDepFileTime)) { + if (forceReadDeps || depFileTime.Compare(internalDepFileTime) >= 0) { status = false; if (this->Verbose) { cmSystemTools::Stdout(cmStrCat("Dependencies file \"", depFile, @@ -95,59 +96,92 @@ bool cmDependsCompiler::CheckDependencies( } std::vector<std::string> depends; - if (format == "msvc"_s) { - cmsys::ifstream fin(depFile.c_str()); - if (!fin) { - continue; + if (format == "custom"_s) { + std::string prefix; + if (this->LocalGenerator->GetCurrentBinaryDirectory() != + this->LocalGenerator->GetBinaryDirectory()) { + prefix = + cmStrCat(this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetBinaryDirectory(), + this->LocalGenerator->GetCurrentBinaryDirectory()), + '/'); } - std::string line; - if (!isValidPath) { - // insert source as first dependency - depends.push_back(source); - } - while (cmSystemTools::GetLineFromStream(fin, line)) { - depends.emplace_back(std::move(line)); - } - } else { - auto deps = cmReadGccDepfile(depFile.c_str()); + auto deps = cmReadGccDepfile(depFile.c_str(), prefix); if (!deps) { continue; } - // dependencies generated by the compiler contains only one target - depends = std::move(deps->front().paths); - if (depends.empty()) { - // unexpectedly empty, ignore it and continue - continue; - } - - // depending of the effective format of the dependencies file generated - // by the compiler, the target can be wrongly identified as a - // dependency so remove it from the list - if (depends.front() == target) { - depends.erase(depends.begin()); + for (auto& entry : *deps) { + depends = std::move(entry.paths); + if (isValidPath) { + cm::erase_if(depends, isValidPath); + } + // copy depends for each target, except first one, which can be + // moved + for (auto index = entry.rules.size() - 1; index > 0; --index) { + dependencies[entry.rules[index]] = depends; + } + dependencies[entry.rules.front()] = std::move(depends); } + } else { + if (format == "msvc"_s) { + cmsys::ifstream fin(depFile.c_str()); + if (!fin) { + continue; + } - // ensure source file is the first dependency - if (depends.front() != source) { - cm::erase(depends, source); + std::string line; if (!isValidPath) { - depends.insert(depends.begin(), source); + // insert source as first dependency + depends.push_back(source); + } + while (cmSystemTools::GetLineFromStream(fin, line)) { + depends.emplace_back(std::move(line)); + } + } else if (format == "gcc"_s) { + auto deps = cmReadGccDepfile(depFile.c_str()); + if (!deps) { + continue; } - } else if (isValidPath) { - // remove first dependency because it must not be filtered out - depends.erase(depends.begin()); + + // dependencies generated by the compiler contains only one target + depends = std::move(deps->front().paths); + if (depends.empty()) { + // unexpectedly empty, ignore it and continue + continue; + } + + // depending of the effective format of the dependencies file + // generated by the compiler, the target can be wrongly identified + // as a dependency so remove it from the list + if (depends.front() == target) { + depends.erase(depends.begin()); + } + + // ensure source file is the first dependency + if (depends.front() != source) { + cm::erase(depends, source); + if (!isValidPath) { + depends.insert(depends.begin(), source); + } + } else if (isValidPath) { + // remove first dependency because it must not be filtered out + depends.erase(depends.begin()); + } + } else { + // unknown format, ignore it + continue; } - } - if (isValidPath) { - cm::erase_if(depends, isValidPath); - // insert source as first dependency - depends.insert(depends.begin(), source); - } + if (isValidPath) { + cm::erase_if(depends, isValidPath); + // insert source as first dependency + depends.insert(depends.begin(), source); + } - dependencies[target] = std::move(depends); + dependencies[target] = std::move(depends); + } } } @@ -168,6 +202,8 @@ void cmDependsCompiler::WriteDependencies( // external dependencies file for (auto& node : makeDependencies) { + auto target = LocalGenerator->ConvertToMakefilePath( + this->LocalGenerator->MaybeConvertToRelativePath(binDir, node.first)); auto& deps = node.second; std::transform( deps.cbegin(), deps.cend(), deps.begin(), @@ -176,13 +212,16 @@ void cmDependsCompiler::WriteDependencies( this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep)); }); - makeDepends << this->LocalGenerator->ConvertToMakefilePath(node.first) - << ": " << deps.front(); - // first dependency is the source, remove it because should not be declared - // as phony target - deps.erase(deps.begin()); + bool first_dep = true; + makeDepends << target << ": "; for (const auto& dep : deps) { - makeDepends << ' ' << lineContinue << " " << dep; + if (first_dep) { + first_dep = false; + makeDepends << dep; + } else { + makeDepends << ' ' << lineContinue << " " << dep; + } + phonyTargets.emplace(dep.data(), dep.length()); } makeDepends << std::endl << std::endl; diff --git a/Source/cmGccDepfileReader.cxx b/Source/cmGccDepfileReader.cxx index eb3511a..96a562e 100644 --- a/Source/cmGccDepfileReader.cxx +++ b/Source/cmGccDepfileReader.cxx @@ -4,10 +4,13 @@ #include <type_traits> #include <utility> +#include <vector> #include <cm/optional> #include "cmGccDepfileLexerHelper.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath) { @@ -17,3 +20,34 @@ cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath) } return cm::nullopt; } + +cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath, + const std::string& prefix) +{ + auto deps = cmReadGccDepfile(filePath); + + if (prefix.empty() || !deps) { + return deps; + } + + for (auto& dep : *deps) { + for (auto& rule : dep.rules) { + if (!cmSystemTools::FileIsFullPath(rule)) { + rule = cmStrCat(prefix, rule); + } + if (cmSystemTools::FileIsFullPath(rule)) { + rule = cmSystemTools::CollapseFullPath(rule); + } + } + for (auto& path : dep.paths) { + if (!cmSystemTools::FileIsFullPath(path)) { + path = cmStrCat(prefix, path); + } + if (cmSystemTools::FileIsFullPath(path)) { + path = cmSystemTools::CollapseFullPath(path); + } + } + } + + return deps; +} diff --git a/Source/cmGccDepfileReader.h b/Source/cmGccDepfileReader.h index 59ed7fd..66ff75d 100644 --- a/Source/cmGccDepfileReader.h +++ b/Source/cmGccDepfileReader.h @@ -2,8 +2,16 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #pragma once +#include <string> + #include <cm/optional> #include "cmGccDepfileReaderTypes.h" cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath); + +/* + * Read dependencies file and append prefix to all relative paths + */ +cm::optional<cmGccDepfileContent> cmReadGccDepfile(const char* filePath, + const std::string& prefix); diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 6459771..09679a7 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -93,6 +93,12 @@ public: */ static bool SupportsPlatform() { return false; } + /** + * Utilized to determine if this generator + * supports DEPFILE option. + */ + bool SupportsCustomCommandDepfile() const override { return true; } + /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index b6fedaf..d59d382 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -3213,36 +3213,43 @@ void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings, if (!attr) { settings->AddAttribute(attribute, value); } else { - if (value->GetType() != cmXCodeObject::OBJECT_LIST && - value->GetType() != cmXCodeObject::STRING) { - cmSystemTools::Error("Unsupported value type for appending: " + - std::string(attribute)); - return; - } - if (attr->GetType() == cmXCodeObject::OBJECT_LIST) { - if (value->GetType() == cmXCodeObject::OBJECT_LIST) { - for (auto* obj : value->GetObjectList()) { - attr->AddObject(obj); - } - } else { - attr->AddObject(value); - } - } else if (attr->GetType() == cmXCodeObject::STRING) { - if (value->GetType() == cmXCodeObject::OBJECT_LIST) { - // Add old value as a list item to new object list - // and replace the attribute with the new list - value->PrependObject(attr); - settings->AddAttribute(attribute, value); - } else { - std::string newValue = - cmStrCat(attr->GetString(), ' ', value->GetString()); - attr->SetString(newValue); - } - } else { - cmSystemTools::Error("Unsupported attribute type for appending: " + - std::string(attribute)); + this->AppendBuildSettingAttribute(settings, attribute, attr, value); + } + } +} + +void cmGlobalXCodeGenerator::AppendBuildSettingAttribute( + cmXCodeObject* settings, const char* attribute, cmXCodeObject* attr, + cmXCodeObject* value) +{ + if (value->GetType() != cmXCodeObject::OBJECT_LIST && + value->GetType() != cmXCodeObject::STRING) { + cmSystemTools::Error("Unsupported value type for appending: " + + std::string(attribute)); + return; + } + if (attr->GetType() == cmXCodeObject::OBJECT_LIST) { + if (value->GetType() == cmXCodeObject::OBJECT_LIST) { + for (auto* obj : value->GetObjectList()) { + attr->AddObject(obj); } + } else { + attr->AddObject(value); } + } else if (attr->GetType() == cmXCodeObject::STRING) { + if (value->GetType() == cmXCodeObject::OBJECT_LIST) { + // Add old value as a list item to new object list + // and replace the attribute with the new list + value->PrependObject(attr); + settings->AddAttribute(attribute, value); + } else { + std::string newValue = + cmStrCat(attr->GetString(), ' ', value->GetString()); + attr->SetString(newValue); + } + } else { + cmSystemTools::Error("Unsupported attribute type for appending: " + + std::string(attribute)); } } @@ -3265,6 +3272,24 @@ void cmGlobalXCodeGenerator::AppendBuildSettingAttribute( } } +void cmGlobalXCodeGenerator::InheritBuildSettingAttribute( + cmXCodeObject* target, const char* attribute) +{ + cmXCodeObject* configurationList = + target->GetAttribute("buildConfigurationList")->GetObject(); + cmXCodeObject* buildConfigs = + configurationList->GetAttribute("buildConfigurations"); + for (auto obj : buildConfigs->GetObjectList()) { + cmXCodeObject* settings = obj->GetAttribute("buildSettings"); + if (cmXCodeObject* attr = settings->GetAttribute(attribute)) { + BuildObjectListOrString inherited(this, true); + inherited.Add("$(inherited)"); + this->AppendBuildSettingAttribute(settings, attribute, attr, + inherited.CreateList()); + } + } +} + void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) { cmGeneratorTarget* gt = target->GetTarget(); @@ -3581,11 +3606,11 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) for (auto& libDir : linkSearchPaths) { libSearchPaths.Add(this->XCodeEscapePath(libDir)); } - // Add paths defined in project-wide build settings - libSearchPaths.Add("$(inherited)"); - this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS", - libSearchPaths.CreateList(), - configName); + if (!libSearchPaths.IsEmpty()) { + this->AppendBuildSettingAttribute(target, "LIBRARY_SEARCH_PATHS", + libSearchPaths.CreateList(), + configName); + } } // add framework search paths @@ -3596,11 +3621,11 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) for (auto& fwDir : frameworkSearchPaths) { fwSearchPaths.Add(this->XCodeEscapePath(fwDir)); } - // Add paths defined in project-wide build settings - fwSearchPaths.Add("$(inherited)"); - this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS", - fwSearchPaths.CreateList(), - configName); + if (!fwSearchPaths.IsEmpty()) { + this->AppendBuildSettingAttribute(target, "FRAMEWORK_SEARCH_PATHS", + fwSearchPaths.CreateList(), + configName); + } } // now add the left-over link libraries @@ -4154,6 +4179,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( for (auto t : targets) { this->AddDependAndLinkInformation(t); this->AddEmbeddedFrameworks(t); + // Inherit project-wide values for any target-specific search paths. + this->InheritBuildSettingAttribute(t, "HEADER_SEARCH_PATHS"); + this->InheritBuildSettingAttribute(t, "SYSTEM_HEADER_SEARCH_PATHS"); + this->InheritBuildSettingAttribute(t, "FRAMEWORK_SEARCH_PATHS"); + this->InheritBuildSettingAttribute(t, "SYSTEM_FRAMEWORK_SEARCH_PATHS"); + this->InheritBuildSettingAttribute(t, "LIBRARY_SEARCH_PATHS"); + this->InheritBuildSettingAttribute(t, "LD_RUNPATH_SEARCH_PATHS"); } if (this->XcodeBuildSystem == BuildSystem::One) { diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 3cc4efe..14db1dc 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -182,9 +182,14 @@ private: cmGeneratorTarget* gtgt); void AppendOrAddBuildSetting(cmXCodeObject* settings, const char* attr, cmXCodeObject* value); + void AppendBuildSettingAttribute(cmXCodeObject* settings, + const char* attribute, cmXCodeObject* attr, + cmXCodeObject* value); void AppendBuildSettingAttribute(cmXCodeObject* target, const char* attr, cmXCodeObject* value, const std::string& configName); + void InheritBuildSettingAttribute(cmXCodeObject* target, + const char* attribute); cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt); void AddDependAndLinkInformation(cmXCodeObject* target); void AddEmbeddedFrameworks(cmXCodeObject* target); diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 08cefb7..358df9d 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -13,6 +13,7 @@ #include <cm/string_view> #include <cm/vector> #include <cmext/algorithm> +#include <cmext/string_view> #include "cmsys/FStream.hxx" #include "cmsys/Terminal.h" @@ -1435,7 +1436,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies( this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES"); if (!depends.empty()) { // dependencies are managed by compiler - auto depFiles = cmExpandedList(depends); + auto depFiles = cmExpandedList(depends, true); std::string const internalDepFile = targetDir + "/compiler_depend.internal"; std::string const depFile = targetDir + "/compiler_depend.make"; @@ -1998,18 +1999,32 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo( cmakefileStream << "\n# The set of dependency files which are needed:\n"; cmakefileStream << "set(CMAKE_DEPENDS_DEPENDENCY_FILES\n"; for (auto const& compilerLang : compilerLangs) { - auto depFormat = this->Makefile->GetSafeDefinition( - cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT")); auto const& compilerPairs = compilerLang.second; - for (auto const& compilerPair : compilerPairs) { - for (auto const& src : compilerPair.second) { - cmakefileStream << " \"" << src << "\" \"" - << this->MaybeConvertToRelativePath( - this->GetBinaryDirectory(), compilerPair.first) - << "\" \"" << depFormat << "\" \"" - << this->MaybeConvertToRelativePath( - this->GetBinaryDirectory(), compilerPair.first) - << ".d\"\n"; + if (compilerLang.first == "CUSTOM"_s) { + for (auto const& compilerPair : compilerPairs) { + for (auto const& src : compilerPair.second) { + cmakefileStream << R"( "" ")" + << this->MaybeConvertToRelativePath( + this->GetBinaryDirectory(), compilerPair.first) + << R"(" "custom" ")" + << this->MaybeConvertToRelativePath( + this->GetBinaryDirectory(), src) + << "\"\n"; + } + } + } else { + auto depFormat = this->Makefile->GetSafeDefinition( + cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT")); + for (auto const& compilerPair : compilerPairs) { + for (auto const& src : compilerPair.second) { + cmakefileStream << " \"" << src << "\" \"" + << this->MaybeConvertToRelativePath( + this->GetBinaryDirectory(), compilerPair.first) + << "\" \"" << depFormat << "\" \"" + << this->MaybeConvertToRelativePath( + this->GetBinaryDirectory(), compilerPair.first) + << ".d\"\n"; + } } } } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 1f23424..70a0393 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1617,6 +1617,16 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( std::vector<std::string> depends; this->LocalGenerator->AppendCustomDepend(depends, ccg); + if (!ccg.GetCC().GetDepfile().empty()) { + // Add dependency over timestamp file for dependencies management + auto dependTimestamp = cmSystemTools::ConvertToOutputPath( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetBinaryDirectory(), + cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"))); + + depends.push_back(dependTimestamp); + } + // Write the rule. const std::vector<std::string>& outputs = ccg.GetOutputs(); bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, @@ -1653,6 +1663,15 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile( objFullPath, srcFullPath); } + // Setup implicit depend for depfile if any + if (!ccg.GetCC().GetDepfile().empty()) { + std::string objFullPath = cmSystemTools::CollapseFullPath( + outputs[0], this->LocalGenerator->GetCurrentBinaryDirectory()); + this->LocalGenerator->AddImplicitDepends( + this->GeneratorTarget, "CUSTOM", objFullPath, ccg.GetFullDepfile(), + cmDependencyScannerKind::Compiler); + } + this->CustomCommandOutputs.insert(outputs.begin(), outputs.end()); } diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 6c18e48..a885b17 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -15,6 +15,7 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" #include "cmOSXBundleGenerator.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator( @@ -36,10 +37,42 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles() *this->BuildFileStream << "# Utility rule file for " << this->GeneratorTarget->GetName() << ".\n\n"; + const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT") + ? "$(CMAKE_BINARY_DIR)/" + : ""); + + // Include the dependencies for the target. + std::string dependFile = + cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make"); + *this->BuildFileStream + << "# Include any custom commands dependencies for this target.\n" + << this->GlobalGenerator->IncludeDirective << " " << root + << cmSystemTools::ConvertToOutputPath( + this->LocalGenerator->MaybeConvertToRelativePath( + this->LocalGenerator->GetBinaryDirectory(), dependFile)) + << "\n\n"; + if (!cmSystemTools::FileExists(dependFile)) { + // Write an empty dependency file. + cmGeneratedFileStream depFileStream( + dependFile, false, this->GlobalGenerator->GetMakefileEncoding()); + depFileStream << "# Empty custom commands generated dependencies file for " + << this->GeneratorTarget->GetName() << ".\n" + << "# This may be replaced when dependencies are built.\n"; + } + + std::string dependTimestamp = + cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"); + if (!cmSystemTools::FileExists(dependTimestamp)) { + // Write a dependency timestamp file. + cmGeneratedFileStream depFileStream( + dependTimestamp, false, this->GlobalGenerator->GetMakefileEncoding()); + depFileStream << "# CMAKE generated file: DO NOT EDIT!\n" + << "# Timestamp file for custom commands dependencies " + "management for " + << this->GeneratorTarget->GetName() << ".\n"; + } + if (!this->NoRuleMessages) { - const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT") - ? "$(CMAKE_BINARY_DIR)/" - : ""); // Include the progress variables for the target. *this->BuildFileStream << "# Include the progress variables for this target.\n" diff --git a/Source/cmTransformDepfile.cxx b/Source/cmTransformDepfile.cxx index 163d7e0..b91e1ce 100644 --- a/Source/cmTransformDepfile.cxx +++ b/Source/cmTransformDepfile.cxx @@ -13,7 +13,6 @@ #include "cmGccDepfileReader.h" #include "cmGccDepfileReaderTypes.h" -#include "cmStringAlgorithms.h" #include "cmSystemTools.h" namespace { @@ -79,26 +78,13 @@ bool cmTransformDepfile(cmDepfileFormat format, const std::string& prefix, { cmGccDepfileContent content; if (cmSystemTools::FileExists(infile)) { - auto result = cmReadGccDepfile(infile.c_str()); + auto result = cmReadGccDepfile(infile.c_str(), prefix); if (!result) { return false; } content = *std::move(result); } - for (auto& dep : content) { - for (auto& rule : dep.rules) { - if (!cmSystemTools::FileIsFullPath(rule)) { - rule = cmStrCat(prefix, rule); - } - } - for (auto& path : dep.paths) { - if (!cmSystemTools::FileIsFullPath(path)) { - path = cmStrCat(prefix, path); - } - } - } - cmsys::ofstream fout(outfile.c_str()); if (!fout) { return false; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index b8464f2..73fbfb6 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1272,6 +1272,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args, cmStateSnapshot snapshot = cm.GetCurrentSnapshot(); snapshot.GetDirectory().SetCurrentBinary(startOutDir); snapshot.GetDirectory().SetCurrentSource(startDir); + snapshot.GetDirectory().SetRelativePathTopSource(homeDir.c_str()); + snapshot.GetDirectory().SetRelativePathTopBinary(homeOutDir.c_str()); cmMakefile mf(cm.GetGlobalGenerator(), snapshot); auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf); diff --git a/Tests/ConfigSources/CMakeLists.txt b/Tests/ConfigSources/CMakeLists.txt index 5513af8..ab0b5d8 100644 --- a/Tests/ConfigSources/CMakeLists.txt +++ b/Tests/ConfigSources/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.0) get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(NOT _isMultiConfig AND NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build") + set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE) endif() project(ConfigSources CXX) diff --git a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-result.txt b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-result.txt index d00491f..d00491f 100644 --- a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-result.txt +++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-result.txt diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-stderr.txt b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-stderr.txt new file mode 100644 index 0000000..cddea3c --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at CustomCommandDependencies-BadArgs.cmake:[0-9]+ \(add_custom_command\): + add_custom_command IMPLICIT_DEPENDS and DEPFILE can not both be specified. +Call Stack \(most recent call first\): + CMakeLists.txt:[0-9]+ \(include\) diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs.cmake new file mode 100644 index 0000000..91ee338 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies-BadArgs.cmake @@ -0,0 +1,10 @@ +enable_language(C) + +add_custom_command(OUTPUT main.c + DEPFILE main.c.d + IMPLICIT_DEPENDS C main.c.in + COMMAND "${CMAKE_COMMAND}" -DINFILE=main.c.in -DOUTFILE=main.c -DDEPFILE=main.c.d + -P "${CMAKE_CURRENT_SOURCE_DIR}/GenerateDepFile.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + +add_custom_target(mainc ALL DEPENDS main.c) diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake new file mode 100644 index 0000000..28bbf11 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.cmake @@ -0,0 +1,73 @@ +enable_language(C) + +add_custom_command(OUTPUT main.c + DEPFILE main.c.d + COMMAND "${CMAKE_COMMAND}" -DINFILE=main.c.in -DOUTFILE=main.c -DDEPFILE=main.c.d + -P "${CMAKE_CURRENT_SOURCE_DIR}/GenerateDepFile.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + +add_custom_target(mainc ALL DEPENDS main.c) + +add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.c) + +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT " +cmake_minimum_required(VERSION 3.19) +set(check_pairs + \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c.in\" + \"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c\" + ) +set(check_exes + \"$<TARGET_FILE:main>\" + ) + +if (check_step EQUAL 2) + include(\"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Makefile.cmake\") + if (NOT CMAKE_DEPEND_INFO_FILES) + set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPEND_INFO_FILES not found.\") + else() + foreach(DEPEND_INFO_FILE IN LISTS CMAKE_DEPEND_INFO_FILES) + include(\"${CMAKE_CURRENT_BINARY_DIR}/\${DEPEND_INFO_FILE}\") + if (NOT CMAKE_DEPENDS_DEPENDENCY_FILES) + set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPENDS_DEPENDENCY_FILES not found.\") + else() + list(LENGTH CMAKE_DEPENDS_DEPENDENCY_FILES DEPENDENCY_FILES_SIZE) + math(EXPR STOP_INDEX \"\${DEPENDENCY_FILES_SIZE} - 1\") + foreach(INDEX RANGE 0 \${STOP_INDEX} 4) + math(EXPR OBJECT_INDEX \"\${INDEX} + 1\") + math(EXPR FORMAT_INDEX \"\${INDEX} + 2\") + math(EXPR DEP_INDEX \"\${INDEX} + 3\") + list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${OBJECT_INDEX} OBJECT_FILE) + list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${FORMAT_INDEX} DEP_FORMAT) + list(GET CMAKE_DEPENDS_DEPENDENCY_FILES \${DEP_INDEX} DEP_FILE) + if (NOT EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/\${DEP_FILE}\") + set(RunCMake_TEST_FAILED \"File \${DEP_FILE} not found.\") + else() + cmake_path(APPEND TARGET_DEP_FILE \"${CMAKE_CURRENT_BINARY_DIR}\" \"\${DEPEND_INFO_FILE}\") + cmake_path(REPLACE_FILENAME TARGET_DEP_FILE \"compiler_depend.make\") + file(READ \"\${TARGET_DEP_FILE}\" DEPENDS_CONTENT) + if (WIN32) + string (REPLACE \"\\\\\" \"/\" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\") + string (TOLOWER \"\${DEPENDS_CONTENT}\" DEPENDS_CONTENT) + string (TOLOWER \"\${OBJECT_FILE}\" OBJECT_FILE) + else() + string(REPLACE \"\\\\ \" \" \" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\") + endif() + if(DEPEND_INFO_FILE MATCHES \"main\\\\.dir\") + if (DEP_FORMAT STREQUAL \"gcc\" AND NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c\") + set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\") + endif() + if (DEP_FORMAT STREQUAL \"custom\" AND NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c.in\") + set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\") + endif() + else() + if (NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c.in\") + set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated:\\n\${DEPENDS_CONTENT}\") + endif() + endif() + endif() + endforeach() + endif() + endforeach() + endif() +endif() +") diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies.step1.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.step1.cmake new file mode 100644 index 0000000..87576eb --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.step1.cmake @@ -0,0 +1,3 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[ +int main(void) { return 1; } +]]) diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDependencies.step2.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.step2.cmake new file mode 100644 index 0000000..69b21b8 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDependencies.step2.cmake @@ -0,0 +1,3 @@ +file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c.in" [[ +int main(void) { return 2; } +]]) diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake new file mode 100644 index 0000000..6ac1291 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.cmake @@ -0,0 +1,61 @@ +cmake_policy(SET CMP0116 NEW) +enable_language(C) + +add_custom_command( + OUTPUT topcc.c + DEPFILE topcc.c.d + COMMAND ${CMAKE_COMMAND} -DOUTFILE=topcc.c -DINFILE=topccdep.txt -DDEPFILE=topcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake" + ) +add_custom_target(topcc ALL DEPENDS topcc.c) + +add_custom_command( + OUTPUT topexe.c + DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/topexe.c.d + COMMAND ${CMAKE_COMMAND} -DOUTFILE=topexe.c "-DINFILE=${CMAKE_CURRENT_BINARY_DIR}/topexedep.txt" -DDEPFILE=topexe.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake" + ) +add_executable(topexe "${CMAKE_CURRENT_BINARY_DIR}/topexe.c") + +add_custom_command( + OUTPUT toplib.c + DEPFILE toplib.c.d + COMMAND ${CMAKE_COMMAND} -DOUTFILE=toplib.c -DINFILE=toplibdep.txt -DDEPFILE=toplib.c.d -P "${CMAKE_CURRENT_LIST_DIR}/WriteDepfile.cmake" + ) +add_library(toplib STATIC toplib.c) + +add_subdirectory(DepfileSubdir) + +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT " +function(check_exists file) + if(NOT EXISTS \"\${file}\") + string(APPEND RunCMake_TEST_FAILED \"\${file} does not exist\\n\") + endif() + set(RunCMake_TEST_FAILED \"\${RunCMake_TEST_FAILED}\" PARENT_SCOPE) +endfunction() + +function(check_not_exists file) + if(EXISTS \"\${file}\") + string(APPEND RunCMake_TEST_FAILED \"\${file} exists\\n\") + endif() + set(RunCMake_TEST_FAILED \"\${RunCMake_TEST_FAILED}\" PARENT_SCOPE) +endfunction() + +set(check_pairs + \"${CMAKE_BINARY_DIR}/topcc.c|${CMAKE_BINARY_DIR}/topccdep.txt\" + \"$<TARGET_FILE:topexe>|${CMAKE_BINARY_DIR}/topexedep.txt\" + \"$<TARGET_FILE:toplib>|${CMAKE_BINARY_DIR}/toplibdep.txt\" + \"${CMAKE_BINARY_DIR}/DepfileSubdir/subcc.c|${CMAKE_BINARY_DIR}/DepfileSubdir/subccdep.txt\" + \"$<TARGET_FILE:subexe>|${CMAKE_BINARY_DIR}/DepfileSubdir/subexedep.txt\" + \"$<TARGET_FILE:sublib>|${CMAKE_BINARY_DIR}/DepfileSubdir/sublibdep.txt\" + ) + +if(check_step EQUAL 3) + list(APPEND check_pairs + \"${CMAKE_BINARY_DIR}/step3.timestamp|${CMAKE_BINARY_DIR}/topcc.c\" + \"${CMAKE_BINARY_DIR}/step3.timestamp|$<TARGET_FILE:topexe>\" + \"${CMAKE_BINARY_DIR}/step3.timestamp|$<TARGET_FILE:toplib>\" + \"${CMAKE_BINARY_DIR}/step3.timestamp|${CMAKE_BINARY_DIR}/DepfileSubdir/subcc.c\" + \"${CMAKE_BINARY_DIR}/step3.timestamp|$<TARGET_FILE:subexe>\" + \"${CMAKE_BINARY_DIR}/step3.timestamp|$<TARGET_FILE:sublib>\" + ) +endif() +") diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step1.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step1.cmake new file mode 100644 index 0000000..0dfe78e --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step1.cmake @@ -0,0 +1,10 @@ +file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir") +file(REMOVE "${RunCMake_TEST_BINARY_DIR}/../sublib.c") +file(REMOVE "${RunCMake_TEST_BINARY_DIR}/step3.timestamp") + +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topccdep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topexedep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/toplibdep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/subccdep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/subexedep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/sublibdep.txt") diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step2.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step2.cmake new file mode 100644 index 0000000..c711514 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step2.cmake @@ -0,0 +1,6 @@ +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topccdep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/topexedep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/toplibdep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/subccdep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/subexedep.txt") +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/DepfileSubdir/sublibdep.txt") diff --git a/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step3.cmake b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step3.cmake new file mode 100644 index 0000000..c55ccc1 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/CustomCommandDepfile.step3.cmake @@ -0,0 +1 @@ +file(TOUCH "${RunCMake_TEST_BINARY_DIR}/step3.timestamp") diff --git a/Tests/RunCMake/BuildDepends/DepfileSubdir/CMakeLists.txt b/Tests/RunCMake/BuildDepends/DepfileSubdir/CMakeLists.txt new file mode 100644 index 0000000..06db47c --- /dev/null +++ b/Tests/RunCMake/BuildDepends/DepfileSubdir/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_policy(SET CMP0116 NEW) + +add_custom_command( + OUTPUT subcc.c + DEPFILE subcc.c.d + COMMAND ${CMAKE_COMMAND} -DOUTFILE=subcc.c -DINFILE=subccdep.txt -DDEPFILE=subcc.c.d -P "${CMAKE_CURRENT_LIST_DIR}/../WriteDepfile.cmake" + ) +add_custom_target(subcc ALL DEPENDS subcc.c) + +add_custom_command( + OUTPUT subexe.c + DEPFILE subexe.c.d + COMMAND ${CMAKE_COMMAND} -DOUTFILE=subexe.c -DINFILE=subexedep.txt -DDEPFILE=subexe.c.d -P "${CMAKE_CURRENT_LIST_DIR}/../WriteDepfile.cmake" + ) +add_executable(subexe subexe.c) + +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/../sublib.c + DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/sublib.c.d + COMMAND ${CMAKE_COMMAND} -DOUTFILE=${CMAKE_BINARY_DIR}/../sublib.c "-DINFILE=${CMAKE_CURRENT_BINARY_DIR}/sublibdep.txt" -DDEPFILE=sublib.c.d -P "${CMAKE_CURRENT_LIST_DIR}/../WriteDepfile.cmake" + ) +add_library(sublib STATIC "${CMAKE_BINARY_DIR}/../sublib.c") diff --git a/Tests/RunCMake/BuildDepends/GenerateDepFile.cmake b/Tests/RunCMake/BuildDepends/GenerateDepFile.cmake new file mode 100644 index 0000000..f7d0f13 --- /dev/null +++ b/Tests/RunCMake/BuildDepends/GenerateDepFile.cmake @@ -0,0 +1,6 @@ +file(READ "${INFILE}" INCONTENT) +file(WRITE "${OUTFILE}" "${INCONTENT}") + +string(REPLACE [[ ]] [[\ ]] OUTFILE "${OUTFILE}") +string(REPLACE [[ ]] [[\ ]] INFILE "${INFILE}") +file(WRITE "${DEPFILE}" "${OUTFILE}: ${INFILE}\n") diff --git a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake index 23e222a..1b7b8d9 100644 --- a/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake +++ b/Tests/RunCMake/BuildDepends/RunCMakeTest.cmake @@ -30,8 +30,17 @@ function(run_BuildDepends CASE) include(${RunCMake_SOURCE_DIR}/${CASE}.step2.cmake OPTIONAL) set(check_step 2) run_cmake_command(${CASE}-build2 ${CMAKE_COMMAND} --build . --config Debug) + if(run_BuildDepends_skip_step_3) + return() + endif() + execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${fs_delay}) # handle 1s resolution + include(${RunCMake_SOURCE_DIR}/${CASE}.step3.cmake OPTIONAL) + set(check_step 3) + run_cmake_command(${CASE}-build3 ${CMAKE_COMMAND} --build . --config Debug) endfunction() +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 @@ -122,4 +131,15 @@ if ((RunCMake_GENERATOR STREQUAL "Unix Makefiles" AND MSVC_VERSION GREATER 1300 AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")) run_BuildDepends(CompilerDependencies) + run_BuildDepends(CustomCommandDependencies) +endif() + +if (RunCMake_GENERATOR MATCHES "Makefiles") + run_cmake(CustomCommandDependencies-BadArgs) +endif() + +if(RunCMake_GENERATOR MATCHES "Make|Ninja") + unset(run_BuildDepends_skip_step_3) + run_BuildDepends(CustomCommandDepfile) + set(run_BuildDepends_skip_step_3 1) endif() diff --git a/Tests/RunCMake/BuildDepends/WriteDepfile.cmake b/Tests/RunCMake/BuildDepends/WriteDepfile.cmake new file mode 100644 index 0000000..c958cde --- /dev/null +++ b/Tests/RunCMake/BuildDepends/WriteDepfile.cmake @@ -0,0 +1,8 @@ +file(WRITE "${OUTFILE}" [[int main(void) +{ + return 0; +} +]]) +string(REPLACE [[ ]] [[\ ]] OUTFILE "${OUTFILE}") +string(REPLACE [[ ]] [[\ ]] INFILE "${INFILE}") +file(WRITE "${DEPFILE}" "${OUTFILE}: ${INFILE}\n") diff --git a/Tests/RunCMake/FetchContent/ManualSourceDirectoryRelative-stderr.txt b/Tests/RunCMake/FetchContent/ManualSourceDirectoryRelative-stderr.txt new file mode 100644 index 0000000..3defcb4 --- /dev/null +++ b/Tests/RunCMake/FetchContent/ManualSourceDirectoryRelative-stderr.txt @@ -0,0 +1,3 @@ + *Relative source directory specified. This is not safe, as it depends on + *the calling directory scope. ++ *FETCHCONTENT_SOURCE_DIR_WITHPROJECT --> WithProject diff --git a/Tests/RunCMake/FetchContent/ManualSourceDirectoryRelative.cmake b/Tests/RunCMake/FetchContent/ManualSourceDirectoryRelative.cmake new file mode 100644 index 0000000..d8b42ba --- /dev/null +++ b/Tests/RunCMake/FetchContent/ManualSourceDirectoryRelative.cmake @@ -0,0 +1 @@ +include(ManualSourceDirectory.cmake) diff --git a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake index 3eb331f..9baeab7 100644 --- a/Tests/RunCMake/FetchContent/RunCMakeTest.cmake +++ b/Tests/RunCMake/FetchContent/RunCMakeTest.cmake @@ -21,6 +21,11 @@ run_cmake_with_options(ManualSourceDirectory run_cmake_with_options(ManualSourceDirectoryMissing -D "FETCHCONTENT_SOURCE_DIR_WITHPROJECT=${CMAKE_CURRENT_LIST_DIR}/ADirThatDoesNotExist" ) +# Need to use :STRING to prevent CMake from automatically converting it to an +# absolute path +run_cmake_with_options(ManualSourceDirectoryRelative + -D "FETCHCONTENT_SOURCE_DIR_WITHPROJECT:STRING=WithProject" +) function(run_FetchContent_DirOverrides) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/DirOverrides-build) diff --git a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-stderr.txt b/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-stderr.txt deleted file mode 100644 index 74d62a4..0000000 --- a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR-stderr.txt +++ /dev/null @@ -1,5 +0,0 @@ -^CMake Error at CustomCommandDepfile-ERROR.cmake:1 \(add_custom_command\): - add_custom_command Option DEPFILE not supported by [^ -]+ -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\)$ diff --git a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR.cmake b/Tests/RunCMake/Make/CustomCommandDepfile-ERROR.cmake deleted file mode 100644 index bad7955..0000000 --- a/Tests/RunCMake/Make/CustomCommandDepfile-ERROR.cmake +++ /dev/null @@ -1,8 +0,0 @@ -add_custom_command( - OUTPUT hello.copy.c - COMMAND "${CMAKE_COMMAND}" -E copy - "${CMAKE_CURRENT_SOURCE_DIR}/hello.c" - hello.copy.c - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - DEPFILE "test.d" - ) diff --git a/Tests/RunCMake/Make/RunCMakeTest.cmake b/Tests/RunCMake/Make/RunCMakeTest.cmake index b66e30e..c7717ec 100644 --- a/Tests/RunCMake/Make/RunCMakeTest.cmake +++ b/Tests/RunCMake/Make/RunCMakeTest.cmake @@ -39,7 +39,6 @@ function(run_VerboseBuild) endfunction() run_VerboseBuild() -run_cmake(CustomCommandDepfile-ERROR) run_cmake(IncludeRegexSubdir) function(run_MakefileConflict) diff --git a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake index abba741..8e0a3bc 100644 --- a/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject/RunCMakeTest.cmake @@ -3,6 +3,7 @@ include(RunCMake) run_cmake(ExplicitCMakeLists) run_cmake(ImplicitCMakeLists) run_cmake(InterfaceLibSources) +run_cmake_with_options(SearchPaths -DCMAKE_CONFIGURATION_TYPES=Debug) run_cmake(XcodeFileType) run_cmake(XcodeAttributeLocation) diff --git a/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake b/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake new file mode 100644 index 0000000..71b7d8f --- /dev/null +++ b/Tests/RunCMake/XcodeProject/SearchPaths-check.cmake @@ -0,0 +1,76 @@ +set(xcProjectFile "${RunCMake_TEST_BINARY_DIR}/SearchPaths.xcodeproj/project.pbxproj") +if(NOT EXISTS "${xcProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${xcProjectFile} does not exist.") + return() +endif() + +set(relevant_lines "") +set(found_project_FRAMEWORK_SEARCH_PATHS 0) +set(found_target_both_FRAMEWORK_SEARCH_PATHS 0) +set(found_target_include_FRAMEWORK_SEARCH_PATHS 0) +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_inherited_LIBRARY_SEARCH_PATHS 0) +file(STRINGS "${xcProjectFile}" lines) +foreach(line IN LISTS lines) + if(line MATCHES [[FRAMEWORK_SEARCH_PATHS]]) + string(APPEND relevant_lines " ${line}\n") + if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = "[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/ProjectSearchPath";]]) + set(found_project_FRAMEWORK_SEARCH_PATHS 1) + endif() + if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathInc(\\")?","(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib(\\")?","\$\(inherited\)"\);]]) + set(found_target_both_FRAMEWORK_SEARCH_PATHS 1) + endif() + if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathInc(\\")?","\$\(inherited\)"\);]]) + set(found_target_include_FRAMEWORK_SEARCH_PATHS 1) + endif() + if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = \("(\\")?[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/TargetSearchPathLib(\\")?","\$\(inherited\)"\);]]) + set(found_target_library_FRAMEWORK_SEARCH_PATHS 1) + endif() + if(line MATCHES [[FRAMEWORK_SEARCH_PATHS = \("\$\(inherited\)"\);]]) + set(found_inherited_FRAMEWORK_SEARCH_PATHS 1) + endif() + endif() + + if(line MATCHES [[LIBRARY_SEARCH_PATHS]]) + string(APPEND relevant_lines " ${line}\n") + if(line MATCHES [[LIBRARY_SEARCH_PATHS = "[^"]*/Tests/RunCMake/XcodeProject/SearchPaths-build/ProjectSearchPath";]]) + set(found_project_LIBRARY_SEARCH_PATHS 1) + endif() + 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 = \("\$\(inherited\)"\);]]) + set(found_inherited_LIBRARY_SEARCH_PATHS 1) + endif() + endif() +endforeach() +if(NOT found_project_FRAMEWORK_SEARCH_PATHS) + string(APPEND RunCMake_TEST_FAILED "Did not find expected FRAMEWORK_SEARCH_PATHS for project in\n ${xcProjectFile}\n") +endif() +if(NOT found_target_both_FRAMEWORK_SEARCH_PATHS) + string(APPEND RunCMake_TEST_FAILED "Did not find expected FRAMEWORK_SEARCH_PATHS for target 'both' in\n ${xcProjectFile}\n") +endif() +if(NOT found_target_include_FRAMEWORK_SEARCH_PATHS) + string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'include' in\n ${xcProjectFile}\n") +endif() +if(NOT found_target_library_FRAMEWORK_SEARCH_PATHS) + string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for target 'library' in\n ${xcProjectFile}\n") +endif() +if(found_inherited_FRAMEWORK_SEARCH_PATHS) + string(APPEND RunCMake_TEST_FAILED "Found unexpected LIBRARY_SEARCH_PATHS inherited-only value in\n ${xcProjectFile}\n") +endif() +if(NOT found_project_LIBRARY_SEARCH_PATHS) + string(APPEND RunCMake_TEST_FAILED "Did not find expected LIBRARY_SEARCH_PATHS for project in\n ${xcProjectFile}\n") +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(found_inherited_LIBRARY_SEARCH_PATHS) + string(APPEND RunCMake_TEST_FAILED "Found unexpected LIBRARY_SEARCH_PATHS inherited-only value in\n ${xcProjectFile}\n") +endif() +if(RunCMake_TEST_FAILED) + string(APPEND RunCMake_TEST_FAILED "Relevant lines include\n${relevant_lines}") +endif() diff --git a/Tests/RunCMake/XcodeProject/SearchPaths.cmake b/Tests/RunCMake/XcodeProject/SearchPaths.cmake new file mode 100644 index 0000000..ef97709 --- /dev/null +++ b/Tests/RunCMake/XcodeProject/SearchPaths.cmake @@ -0,0 +1,21 @@ +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") + +set(CMAKE_XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath") +set(CMAKE_XCODE_ATTRIBUTE_LIBRARY_SEARCH_PATHS "${CMAKE_CURRENT_BINARY_DIR}/ProjectSearchPath") + +add_executable(neither main.c) + +add_executable(both main.c) +target_include_directories(both PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathInc/TargetInc.framework") +target_link_libraries(both PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathLib/TargetLib.framework") + +add_executable(include main.c) +target_include_directories(include PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/TargetSearchPathInc/TargetInc.framework") + +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") diff --git a/Utilities/Release/linux/aarch64/Dockerfile b/Utilities/Release/linux/aarch64/Dockerfile new file mode 100644 index 0000000..4077b79 --- /dev/null +++ b/Utilities/Release/linux/aarch64/Dockerfile @@ -0,0 +1,35 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# Produce an image containing a portable CMake binary package for Linux/aarch64. +# Build using the CMake source directory as the build context. +# The resulting image will have an '/out' directory containing the package. + +# Keep this in sync with the `.gitlab-ci.yml` `release_linux` image. +ARG FROM_IMAGE_NAME=kitware/cmake:build-linux-aarch64-deps-2020-12-21 +ARG FROM_IMAGE_DIGEST=@sha256:0bd7dfe4e45593b04e39cd21e44011034610cfd376900558c5ef959bb1af15af +ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST +FROM $FROM_IMAGE + +COPY . /opt/cmake/src/cmake + +ARG TEST=true + +RUN : \ + && mkdir -p /opt/cmake/src/cmake-build \ + && cd /opt/cmake/src/cmake-build \ + && cp ../cmake/Utilities/Release/linux/aarch64/cache.txt CMakeCache.txt \ + && source /opt/rh/devtoolset-7/enable \ + && set -x \ + && ../cmake/bootstrap --parallel=$(nproc) --docdir=doc/cmake \ + && 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)'; \ + fi \ + && bin/cpack -G TGZ \ + && bin/cpack -G STGZ \ + && set +x \ + && mkdir /out \ + && mv cmake-*-Linux-aarch64.* /out \ + && : diff --git a/Utilities/Release/linux/aarch64/base/Dockerfile b/Utilities/Release/linux/aarch64/base/Dockerfile new file mode 100644 index 0000000..b9c683e --- /dev/null +++ b/Utilities/Release/linux/aarch64/base/Dockerfile @@ -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. + +# Produce a base image with a build environment for portable CMake binaries. +# Build using the directory containing this file as its own build context. + +ARG FROM_IMAGE_NAME=centos:7 +ARG FROM_IMAGE_DIGEST=@sha256:43964203bf5d7fe38c6fca6166ac89e4c095e2b0c0a28f6c7c678a1348ddc7fa +ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST +FROM $FROM_IMAGE + +RUN : \ + && yum install -y centos-release-scl \ + && yum install -y \ + ca-certificates \ + curl \ + devtoolset-7-gcc \ + devtoolset-7-gcc-c++ \ + fontconfig-devel \ + freetype-devel \ + git \ + libX11-devel \ + libxcb-devel \ + make \ + patch \ + perl \ + python3-pip \ + xz \ + which \ + && yum clean all \ + && : diff --git a/Utilities/Release/linux/aarch64/cache.txt b/Utilities/Release/linux/aarch64/cache.txt new file mode 100644 index 0000000..89050d1 --- /dev/null +++ b/Utilities/Release/linux/aarch64/cache.txt @@ -0,0 +1,44 @@ +CMAKE_BUILD_TYPE:STRING=Release + +CMAKE_C_STANDARD:STRING=11 +CMAKE_CXX_STANDARD:STRING=14 + +# Require only older APIs where possible. +CMAKE_C_FLAGS:STRING=-D_POSIX_C_SOURCE=199506L -D_POSIX_SOURCE=1 -D_SVID_SOURCE=1 -D_BSD_SOURCE=1 + +# Link C++ library statically. +CMAKE_EXE_LINKER_FLAGS:STRING=-static-libstdc++ -static-libgcc + +# Enable ssl support in curl +CMAKE_USE_OPENSSL:BOOL=ON +OPENSSL_CRYPTO_LIBRARY:STRING=/opt/openssl/lib/libcrypto.a;-pthread +OPENSSL_INCLUDE_DIR:PATH=/opt/openssl/include +OPENSSL_SSL_LIBRARY:FILEPATH=/opt/openssl/lib/libssl.a + +# Enable ccmake +BUILD_CursesDialog:BOOL=ON +CURSES_FORM_LIBRARY:FILEPATH=/opt/ncurses/lib/libform.a +CURSES_INCLUDE_PATH:PATH=/opt/ncurses/include +CURSES_NCURSES_LIBRARY:FILEPATH=/opt/ncurses/lib/libncurses.a + +# Enable cmake-gui with static qt plugins +BUILD_QtDialog:BOOL=TRUE +CMake_GUI_DISTRIBUTE_WITH_Qt_LGPL:STRING=3 +CMAKE_PREFIX_PATH:STRING=/opt/qt +CMake_QT_STATIC_QXcbIntegrationPlugin_LIBRARIES:STRING=/opt/qt/plugins/platforms/libqxcb.a;/opt/qt/lib/libQt5XcbQpa.a;/opt/qt/lib/libQt5ServiceSupport.a;/opt/qt/lib/libQt5EdidSupport.a;/opt/qt/lib/libQt5EventDispatcherSupport.a;/opt/qt/lib/libQt5FontDatabaseSupport.a;/opt/qt/lib/libQt5ThemeSupport.a;/opt/qt/lib/libxcb-static.a;-lxcb;-lfontconfig;-lfreetype + +# Build documentation. +SPHINX_EXECUTABLE:FILEPATH=/usr/local/bin/sphinx-build +SPHINX_HTML:BOOL=ON +SPHINX_MAN:BOOL=ON +SPHINX_QTHELP:BOOL=ON +QCOLLECTIONGENERATOR_EXECUTABLE:PATH=/opt/qt/bin/qhelpgenerator + +# We bootstrap as part of the build so skip its test. +CMAKE_SKIP_BOOTSTRAP_TEST:STRING=TRUE + +# Skip Qt5 tests because our Qt is static. +CMake_TEST_Qt5:BOOL=FALSE + +# CPack package file name component for this platform. +CPACK_SYSTEM_NAME:STRING=Linux-aarch64 diff --git a/Utilities/Release/linux/aarch64/deps/Dockerfile b/Utilities/Release/linux/aarch64/deps/Dockerfile new file mode 100644 index 0000000..8d0f6fd --- /dev/null +++ b/Utilities/Release/linux/aarch64/deps/Dockerfile @@ -0,0 +1,141 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# Produce an image with custom-built dependencies for portable CMake binaries. +# Build using the directory containing this file as its own build context. + +ARG FROM_IMAGE_NAME=kitware/cmake:build-linux-aarch64-base-2020-12-21 +ARG FROM_IMAGE_DIGEST=@sha256:c8d9fa279ef09c26e74ff28770ae0db1f4cb75ef53b782ace604daba71a41f65 +ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST +FROM $FROM_IMAGE + +# Sphinx +RUN : \ + && pip3 install sphinx==2.1.2 \ + && : + +# Qt +# Version 5.12.0 was the last to bundle xkbcommon. +COPY qt-install.patch /opt/qt/src/ +RUN : \ + && mkdir -p /opt/qt/src/qt-build \ + && cd /opt/qt/src \ + && curl -OL https://download.qt.io/archive/qt/5.12/5.12.0/single/qt-everywhere-src-5.12.0.tar.xz \ + && sha512sum qt-everywhere-src-5.12.0.tar.xz | grep -q 0dd03d2645fb6dac5b58c8caf92b4a0a6900131f1ccfb02443a0df4702b5da0458f4c45e758d1b929ec709b0f4b36900df2fd60a058af9cc8c1a0748b6d57aae \ + && tar xJf qt-everywhere-src-5.12.0.tar.xz \ + && cd qt-build \ + && source /opt/rh/devtoolset-7/enable \ + && ../qt-everywhere-src-5.12.0/configure \ + -prefix /opt/qt \ + -static \ + -release \ + -c++std c++11 \ + -opensource -confirm-license \ + -gui \ + -widgets \ + -xcb \ + -fontconfig \ + -sql-sqlite \ + -qt-doubleconversion \ + -qt-libjpeg \ + -qt-libpng \ + -qt-pcre \ + -qt-sqlite \ + -qt-xcb \ + -qt-xkbcommon \ + -qt-zlib \ + -system-freetype \ + -no-accessibility \ + -no-compile-examples \ + -no-cups \ + -no-dbus \ + -no-directfb \ + -no-egl \ + -no-eglfs \ + -no-evdev \ + -no-gbm \ + -no-gif \ + -no-glib \ + -no-gtk \ + -no-harfbuzz \ + -no-iconv \ + -no-icu \ + -no-journald \ + -no-kms \ + -no-libinput \ + -no-libproxy \ + -no-linuxfb \ + -no-ltcg \ + -no-mirclient \ + -no-mtdev \ + -no-opengl \ + -no-openssl \ + -no-pch \ + -no-sql-mysql \ + -no-sql-psql \ + -no-sql-sqlite2 \ + -no-syslog \ + -no-system-proxies \ + -no-tslib \ + -no-use-gold-linker \ + -skip declarative \ + -skip multimedia \ + -skip qtcanvas3d \ + -skip qtconnectivity \ + -skip qtdeclarative \ + -skip qtlocation \ + -skip qtmultimedia \ + -skip qtsensors \ + -skip qtserialport \ + -skip qtsvg \ + -skip qtwayland \ + -skip qtwebchannel \ + -skip qtwebengine \ + -skip qtwebsockets \ + -skip qtwinextras \ + -skip qtxmlpatterns \ + -nomake examples \ + -nomake tests \ + && make install -j $(nproc) \ + && cd /opt/qt \ + && patch -p1 -i src/qt-install.patch \ + && cd /opt \ + && rm -rf /opt/qt/src \ + && : + +# Curses +RUN : \ + && mkdir -p /opt/ncurses/src/ncurses-build \ + && cd /opt/ncurses/src \ + && curl -O https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.1.tar.gz \ + && sha512sum ncurses-6.1.tar.gz | grep -q e308af43f8b7e01e98a55f4f6c4ee4d1c39ce09d95399fa555b3f0cdf5fd0db0f4c4d820b4af78a63f6cf6d8627587114a40af48cfc066134b600520808a77ee \ + && tar xzf ncurses-6.1.tar.gz \ + && cd ncurses-build \ + && source /opt/rh/devtoolset-7/enable \ + && ../ncurses-6.1/configure \ + --prefix=/opt/ncurses \ + --with-terminfo-dirs=/etc/terminfo:/lib/terminfo:/usr/share/terminfo \ + --with-default-terminfo-dir=/usr/share/terminfo \ + --without-shared \ + && make -j $(nproc) \ + && make install.libs install.includes \ + && cd /opt \ + && rm -rf /opt/ncurses/src \ + && : + +# OpenSSL +COPY openssl-source.patch /opt/openssl/src/ +RUN : \ + && mkdir -p /opt/openssl/src \ + && cd /opt/openssl/src \ + && curl -O https://www.openssl.org/source/openssl-1.1.1f.tar.gz \ + && sha512sum openssl-1.1.1f.tar.gz | grep -q b00bd9b5ad5298fbceeec6bb19c1ab0c106ca5cfb31178497c58bf7e0e0cf30fcc19c20f84e23af31cc126bf2447d3e4f8461db97bafa7bd78f69561932f000c \ + && tar xzf openssl-1.1.1f.tar.gz \ + && cd openssl-1.1.1f \ + && patch -p1 -i ../openssl-source.patch \ + && source /opt/rh/devtoolset-7/enable \ + && ./Configure --prefix=/opt/openssl linux-elf no-asm no-shared -D_POSIX_C_SOURCE=199506L -D_POSIX_SOURCE=1 -D_SVID_SOURCE=1 -D_BSD_SOURCE=1 \ + && make install_dev -j $(nproc) \ + && cd /opt \ + && rm -rf /opt/openssl/src \ + && : diff --git a/Utilities/Release/linux/aarch64/deps/openssl-source.patch b/Utilities/Release/linux/aarch64/deps/openssl-source.patch new file mode 100644 index 0000000..c81fe2f --- /dev/null +++ b/Utilities/Release/linux/aarch64/deps/openssl-source.patch @@ -0,0 +1,12 @@ +# enable pthread APIs disabled by our _POSIX_SOURCE definitions +--- openssl-source/crypto/threads_pthread.c.orig ++++ openssl-source/crypto/threads_pthread.c +@@ -6,6 +6,8 @@ + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ ++#undef _POSIX_C_SOURCE ++#undef _POSIX_SOURCE + + #include <openssl/crypto.h> + #include "internal/cryptlib.h" diff --git a/Utilities/Release/linux/aarch64/deps/qt-install.patch b/Utilities/Release/linux/aarch64/deps/qt-install.patch new file mode 100644 index 0000000..792aefd --- /dev/null +++ b/Utilities/Release/linux/aarch64/deps/qt-install.patch @@ -0,0 +1,24 @@ +# Add Qt Core dependencies missing from static Qt build. +--- qt-install/lib/cmake/Qt5Core/Qt5CoreConfig.cmake.orig ++++ qt-install/lib/cmake/Qt5Core/Qt5CoreConfig.cmake +@@ -111,7 +111,7 @@ + list(REMOVE_DUPLICATES Qt5Core_COMPILE_DEFINITIONS) + list(REMOVE_DUPLICATES Qt5Core_EXECUTABLE_COMPILE_FLAGS) + +- set(_Qt5Core_LIB_DEPENDENCIES "") ++ set(_Qt5Core_LIB_DEPENDENCIES "${_qt5Core_install_prefix}/lib/libqtpcre2.a") + + + add_library(Qt5::Core STATIC IMPORTED) +# Add Qt Gui dependencies missing from static Qt build. +--- qt-install/lib/cmake/Qt5Gui/Qt5GuiConfig.cmake.orig ++++ qt-install/lib/cmake/Qt5Gui/Qt5GuiConfig.cmake +@@ -111,7 +111,7 @@ + list(REMOVE_DUPLICATES Qt5Gui_COMPILE_DEFINITIONS) + list(REMOVE_DUPLICATES Qt5Gui_EXECUTABLE_COMPILE_FLAGS) + +- set(_Qt5Gui_LIB_DEPENDENCIES "Qt5::Core") ++ set(_Qt5Gui_LIB_DEPENDENCIES "Qt5::Core;${_qt5Gui_install_prefix}/lib/libqtlibpng.a") + + + add_library(Qt5::Gui STATIC IMPORTED) diff --git a/Utilities/Release/linux/aarch64/test/Dockerfile b/Utilities/Release/linux/aarch64/test/Dockerfile new file mode 100644 index 0000000..03674fb --- /dev/null +++ b/Utilities/Release/linux/aarch64/test/Dockerfile @@ -0,0 +1,26 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# Produce a base image with a test environment for packaged CMake binaries. +# Build using the directory containing this file as its own build context. + +ARG FROM_IMAGE_NAME=debian:10 +ARG FROM_IMAGE_DIGEST=@sha256:ab0ba5b78bfe01d61ac4f9919cd0e7bef8beefa0a77d3d710bfc8630d96804b8 +ARG FROM_IMAGE=$FROM_IMAGE_NAME$FROM_IMAGE_DIGEST +FROM $FROM_IMAGE + +RUN : \ + && apt-get update \ + && apt-get install -y \ + dpkg \ + file \ + gcc \ + g++ \ + gfortran \ + qt5-default \ + make \ + ninja-build \ + && apt-get clean \ + && : + +COPY test-make.bash test-ninja.bash / diff --git a/Utilities/Release/linux/aarch64/test/test-make.bash b/Utilities/Release/linux/aarch64/test/test-make.bash new file mode 100644 index 0000000..10d30c3 --- /dev/null +++ b/Utilities/Release/linux/aarch64/test/test-make.bash @@ -0,0 +1,17 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +set -e +set -x +mkdir -p /opt/cmake/src/cmake-make +cd /opt/cmake/src/cmake-make +echo >CMakeCache.txt ' +CMake_TEST_IPO_WORKS_C:BOOL=ON +CMake_TEST_IPO_WORKS_CXX:BOOL=ON +CMake_TEST_IPO_WORKS_Fortran:BOOL=ON +CMake_TEST_NO_NETWORK:BOOL=ON +CMake_TEST_Qt5:BOOL=ON +' +cmake ../cmake -DCMake_TEST_HOST_CMAKE=1 -G "Unix Makefiles" +make -j $(nproc) +ctest --output-on-failure -j $(nproc) diff --git a/Utilities/Release/linux/aarch64/test/test-ninja.bash b/Utilities/Release/linux/aarch64/test/test-ninja.bash new file mode 100644 index 0000000..fe39e2e --- /dev/null +++ b/Utilities/Release/linux/aarch64/test/test-ninja.bash @@ -0,0 +1,17 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +set -e +set -x +mkdir -p /opt/cmake/src/cmake-ninja +cd /opt/cmake/src/cmake-ninja +echo >CMakeCache.txt ' +CMAKE_Fortran_COMPILER:STRING= +CMake_TEST_IPO_WORKS_C:BOOL=ON +CMake_TEST_IPO_WORKS_CXX:BOOL=ON +CMake_TEST_NO_NETWORK:BOOL=ON +CMake_TEST_Qt5:BOOL=ON +' +cmake ../cmake -DCMake_TEST_HOST_CMAKE=1 -G "Ninja" +ninja +ctest --output-on-failure -j $(nproc) |