diff --git a/azure-pipelines/end-to-end-tests-dir/backcompat-helpers.ps1 b/azure-pipelines/end-to-end-tests-dir/backcompat-helpers.ps1 index 704b52752..b944e6a86 100644 --- a/azure-pipelines/end-to-end-tests-dir/backcompat-helpers.ps1 +++ b/azure-pipelines/end-to-end-tests-dir/backcompat-helpers.ps1 @@ -13,6 +13,15 @@ foreach ($backcompatFeaturePort in $backcompatFeaturePorts) { throw $CurrentTest } + $failArgs = $succeedArgs + @('--enforce-port-checks') + $CurrentTest = "Should fail: ./vcpkg $($failArgs -join ' ')" + Run-Vcpkg @failArgs + if ($LastExitCode -ne 0) { + Write-Host "... failed (this is good!)." + } else { + throw $CurrentTest + } + # Install failed when prohibiting backcompat features, so it should succeed if we allow them $CurrentTest = "Should succeeed: ./vcpkg $($succeedArgs -join ' ')" Run-Vcpkg @succeedArgs diff --git a/azure-pipelines/pipelines.yml b/azure-pipelines/pipelines.yml index 76c6b1353..551feaf63 100644 --- a/azure-pipelines/pipelines.yml +++ b/azure-pipelines/pipelines.yml @@ -30,7 +30,7 @@ jobs: - job: osx displayName: 'OSX' pool: - vmImage: 'macos-latest' + vmImage: 'macOS-11' variables: - name: 'VCPKG_ROOT' value: $(Build.SourcesDirectory)/vcpkg-root diff --git a/azure-pipelines/signing.yml b/azure-pipelines/signing.yml index 14d998cc8..73a4d2001 100644 --- a/azure-pipelines/signing.yml +++ b/azure-pipelines/signing.yml @@ -28,7 +28,7 @@ jobs: - job: macos_build displayName: 'MacOS Build' pool: - vmImage: macOS-10.15 + vmImage: macOS-11 variables: - group: vcpkg-dependency-source-blobs - name: FMT_TARBALL_URL diff --git a/src/vcpkg/build.cpp b/src/vcpkg/build.cpp index e016d9409..c9a525fb2 100644 --- a/src/vcpkg/build.cpp +++ b/src/vcpkg/build.cpp @@ -956,10 +956,11 @@ namespace vcpkg::Build action.public_abi(), std::move(find_itr->second)); - if (error_count != 0) + if (error_count != 0 && action.build_options.backcompat_features == BackcompatFeatures::PROHIBIT) { return BuildResult::POST_BUILD_CHECKS_FAILED; } + for (auto&& feature : action.feature_list) { for (auto&& f_pgh : scfl.source_control_file->feature_paragraphs) diff --git a/src/vcpkg/install.cpp b/src/vcpkg/install.cpp index fd48d8470..10fc0008c 100644 --- a/src/vcpkg/install.cpp +++ b/src/vcpkg/install.cpp @@ -523,9 +523,10 @@ namespace vcpkg::Install static constexpr StringLiteral OPTION_MANIFEST_NO_DEFAULT_FEATURES = "x-no-default-features"; static constexpr StringLiteral OPTION_MANIFEST_FEATURE = "x-feature"; static constexpr StringLiteral OPTION_PROHIBIT_BACKCOMPAT_FEATURES = "x-prohibit-backcompat-features"; + static constexpr StringLiteral OPTION_ENFORCE_PORT_CHECKS = "enforce-port-checks"; static constexpr StringLiteral OPTION_ALLOW_UNSUPPORTED_PORT = "allow-unsupported"; - static constexpr std::array INSTALL_SWITCHES = {{ + static constexpr std::array INSTALL_SWITCHES = {{ {OPTION_DRY_RUN, "Do not actually build or install"}, {OPTION_USE_HEAD_VERSION, "Install the libraries on the command line using the latest upstream sources"}, {OPTION_NO_DOWNLOADS, "Do not download new sources"}, @@ -540,11 +541,12 @@ namespace vcpkg::Install {OPTION_CLEAN_BUILDTREES_AFTER_BUILD, "Clean buildtrees after building each package"}, {OPTION_CLEAN_PACKAGES_AFTER_BUILD, "Clean packages after building each package"}, {OPTION_CLEAN_DOWNLOADS_AFTER_BUILD, "Clean downloads after building each package"}, - {OPTION_PROHIBIT_BACKCOMPAT_FEATURES, - "(experimental) Fail install if a package attempts to use a deprecated feature"}, + {OPTION_ENFORCE_PORT_CHECKS, + "Fail install if a port has detected problems or attempts to use a deprecated feature"}, + {OPTION_PROHIBIT_BACKCOMPAT_FEATURES, ""}, {OPTION_ALLOW_UNSUPPORTED_PORT, "Instead of erroring on an unsupported port, continue with a warning."}, }}; - static constexpr std::array MANIFEST_INSTALL_SWITCHES = {{ + static constexpr std::array MANIFEST_INSTALL_SWITCHES = {{ {OPTION_DRY_RUN, "Do not actually build or install"}, {OPTION_USE_HEAD_VERSION, "Install the libraries on the command line using the latest upstream sources"}, {OPTION_NO_DOWNLOADS, "Do not download new sources"}, @@ -559,6 +561,9 @@ namespace vcpkg::Install {OPTION_CLEAN_PACKAGES_AFTER_BUILD, "Clean packages after building each package"}, {OPTION_CLEAN_DOWNLOADS_AFTER_BUILD, "Clean downloads after building each package"}, {OPTION_MANIFEST_NO_DEFAULT_FEATURES, "Don't install the default features from the manifest."}, + {OPTION_ENFORCE_PORT_CHECKS, + "Fail install if a port has detected problems or attempts to use a deprecated feature"}, + {OPTION_PROHIBIT_BACKCOMPAT_FEATURES, ""}, {OPTION_ALLOW_UNSUPPORTED_PORT, "Instead of erroring on an unsupported port, continue with a warning."}, }}; @@ -797,7 +802,8 @@ namespace vcpkg::Install const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING) || only_downloads); const bool prohibit_backcompat_features = - Util::Sets::contains(options.switches, (OPTION_PROHIBIT_BACKCOMPAT_FEATURES)); + Util::Sets::contains(options.switches, (OPTION_PROHIBIT_BACKCOMPAT_FEATURES)) || + Util::Sets::contains(options.switches, (OPTION_ENFORCE_PORT_CHECKS)); const auto unsupported_port_action = Util::Sets::contains(options.switches, OPTION_ALLOW_UNSUPPORTED_PORT) ? Dependencies::UnsupportedPortAction::Warn : Dependencies::UnsupportedPortAction::Error; diff --git a/src/vcpkg/postbuildlint.cpp b/src/vcpkg/postbuildlint.cpp index f32c51328..dcb8da55b 100644 --- a/src/vcpkg/postbuildlint.cpp +++ b/src/vcpkg/postbuildlint.cpp @@ -19,7 +19,7 @@ namespace vcpkg::PostBuildLint enum class LintStatus { SUCCESS = 0, - ERROR_DETECTED = 1 + PROBLEM_DETECTED = 1 }; struct OutdatedDynamicCrt @@ -89,7 +89,7 @@ namespace vcpkg::PostBuildLint print2(Color::warning, "The folder /include exists in a cmake helper port; this is incorrect, since only cmake " "files should be installed\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } else { @@ -102,7 +102,7 @@ namespace vcpkg::PostBuildLint print2(Color::warning, "The folder /include is empty or not present. This indicates the library was not correctly " "installed.\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -193,7 +193,7 @@ namespace vcpkg::PostBuildLint print2("In exceptional circumstances, this policy can be disabled via ", Build::to_cmake_variable(BuildPolicy::ALLOW_RESTRICTED_HEADERS), "\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -213,7 +213,7 @@ namespace vcpkg::PostBuildLint "Include files should not be duplicated into the /debug/include directory. If this cannot " "be disabled in the project cmake, use\n" " file(REMOVE_RECURSE \"${CURRENT_PACKAGES_DIR}/debug/include\")\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -227,7 +227,7 @@ namespace vcpkg::PostBuildLint print2(Color::warning, "/debug/share should not exist. Please reorganize any important files, then use\n" " file(REMOVE_RECURSE \"${CURRENT_PACKAGES_DIR}/debug/share\")\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -248,7 +248,7 @@ namespace vcpkg::PostBuildLint "The /", relative_path, " file does not exist. This file must exist for CMake helper ports.\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } } @@ -265,7 +265,7 @@ namespace vcpkg::PostBuildLint "/share/%s/cmake.\nPlease use the helper function `vcpkg_cmake_config_fixup()` " "from the port vcpkg-cmake-config.`\n", spec.name()); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -302,7 +302,7 @@ namespace vcpkg::PostBuildLint spec.name(), spec.name()); print_paths(misplaced_cmake_files); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -318,7 +318,7 @@ namespace vcpkg::PostBuildLint vcpkg::printf(Color::warning, "The /debug/lib/cmake folder should be merged with /lib/cmake into /share/%s\n", spec.name()); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -335,7 +335,7 @@ namespace vcpkg::PostBuildLint "\nThe following dlls were found in /lib or /debug/lib. Please move them to /bin or " "/debug/bin, respectively.\n"); print_paths(dlls); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -391,7 +391,7 @@ namespace vcpkg::PostBuildLint print2(Color::warning, "The following files are potential copyright files:\n"); print_paths(potential_copyright_files); } - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } static LintStatus check_for_exes(const Filesystem& fs, const Path& package_dir) @@ -404,7 +404,7 @@ namespace vcpkg::PostBuildLint print2(Color::warning, "The following EXEs were found in /bin or /debug/bin. EXEs are not valid distribution targets.\n"); print_paths(exes); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -439,7 +439,7 @@ namespace vcpkg::PostBuildLint "If this is intended, add the following line in the portfile:\n" " SET(%s enabled)\n", to_cmake_variable(BuildPolicy::DLLS_WITHOUT_EXPORTS)); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -473,7 +473,7 @@ namespace vcpkg::PostBuildLint print2(Color::warning, "The following DLLs do not have the App Container bit set:\n"); print_paths(dlls_with_improper_uwp_bit); print2(Color::warning, "This bit is required for Windows Store apps.\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -543,7 +543,7 @@ namespace vcpkg::PostBuildLint if (!binaries_with_invalid_architecture.empty()) { print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -582,7 +582,7 @@ namespace vcpkg::PostBuildLint if (!binaries_with_invalid_architecture.empty()) { print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } #endif (void)expected_architecture; @@ -600,7 +600,7 @@ namespace vcpkg::PostBuildLint print2(Color::warning, "DLLs should not be present in a static build, but the following DLLs were found:\n"); print_paths(dlls); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } static LintStatus check_matching_debug_and_release_binaries(const std::vector& debug_binaries, @@ -634,7 +634,7 @@ namespace vcpkg::PostBuildLint print2("\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } static LintStatus check_lib_files_are_available_if_dlls_are_available(const Build::BuildPolicies& policies, @@ -651,7 +651,7 @@ namespace vcpkg::PostBuildLint "If this is intended, add the following line in the portfile:\n" " SET(%s enabled)\n", to_cmake_variable(BuildPolicy::DLLS_WITHOUT_LIBS)); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -701,7 +701,7 @@ namespace vcpkg::PostBuildLint R"###( endif())###" "\n\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } static LintStatus check_no_empty_folders(const Filesystem& fs, const Path& dir) @@ -725,14 +725,15 @@ namespace vcpkg::PostBuildLint "\n" "\n" "\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; } - static LintStatus check_pkgconfig_dir_only_in_lib_dir(const Filesystem& fs, const Path& dir) + static LintStatus check_pkgconfig_dir_only_in_lib_dir(const Filesystem& fs, const Path& dir_raw) { + auto dir = dir_raw.lexically_normal().generic_u8string(); // force /s std::vector misplaced_pkgconfig_files = fs.get_regular_files_recursive(dir, IgnoreErrors{}); Util::erase_remove_if(misplaced_pkgconfig_files, [&fs](const Path& path) { if (!Strings::ends_with(path, ".pc")) return true; @@ -750,18 +751,70 @@ namespace vcpkg::PostBuildLint if (!misplaced_pkgconfig_files.empty()) { - print2(Color::warning, "There should be no pkgconfig directories outside of lib and debug/lib.\n"); + print2(Color::warning, + "pkgconfig directories should be one of share/pkgconfig (for header only libraries only), " + "lib/pkgconfig, or lib/debug/pkgconfig.\n"); print2("The following misplaced pkgconfig files were found:\n"); print_paths(misplaced_pkgconfig_files); - print2( - Color::warning, - "You can move the pkgconfig files with the following commands:\n" - "\n" - R"###( file(INSTALL "${CURRENT_PACKAGES_DIR}/a/path/pkgconfig/name.pc" DESTINATION "${CURRENT_PACKAGES_DIR}/a/path/pkgconfig"))###" - "\n" - R"###( file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/a/path/pkgconfig"))###" - "\n\n"); - return LintStatus::ERROR_DETECTED; + + bool contains_release = false; + bool contains_debug = false; + std::vector misplaced_is_release(misplaced_pkgconfig_files.size()); // vectorish + for (size_t idx = 0; idx < misplaced_pkgconfig_files.size(); ++idx) + { + bool is_release = misplaced_pkgconfig_files[idx].native().find("debug/") == std::string::npos; + misplaced_is_release[idx] = is_release; + if (is_release) + { + contains_release = true; + } + else + { + contains_debug = true; + } + } + + print2(Color::warning, + "You can move the pkgconfig files with commands similar to:\n" + "\n"); + + std::string create_directory_line(" file(MAKE_DIRECTORY "); + if (contains_release) + { + create_directory_line += R"###( "${CURRENT_PACKAGES_DIR}/lib/pkgconfig")###"; + } + + if (contains_debug) + { + create_directory_line += R"###( "${CURRENT_PACKAGES_DIR}/lib/debug/pkgconfig")###"; + } + + create_directory_line.append(")\n"); + + print2(Color::warning, create_directory_line); + + for (size_t idx = 0; idx < misplaced_pkgconfig_files.size(); ++idx) + { + const auto& misplaced = misplaced_pkgconfig_files[idx]; + auto relative = misplaced.native().substr(dir.size()); + std::string rename_line(R"###( file(RENAME "${CURRENT_PACKAGES_DIR})###"); + rename_line.append(relative); + rename_line.append(R"###(" "${CURRENT_PACKAGES_DIR}/)###"); + if (!misplaced_is_release[idx]) + { + rename_line.append("debug/"); + } + + rename_line.append(R"###(lib/pkgconfig/)###"); + rename_line.append(misplaced.filename().to_string()); + rename_line.append("\")\n"); + print2(Color::warning, rename_line); + } + + print2(Color::warning, + " vcpkg_fixup_pkgconfig()\n" + " file(REMOVE_RECURSE empty directories left by the above renames)\n\n"); + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -815,7 +868,7 @@ namespace vcpkg::PostBuildLint print2("\n"); print2(Color::warning, "To inspect the lib files, use:\n dumpbin.exe /directives mylibfile.lib\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -863,7 +916,7 @@ namespace vcpkg::PostBuildLint print2("\n"); print2(Color::warning, "To inspect the dll files, use:\n dumpbin.exe /dependents mydllfile.dll\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -882,7 +935,7 @@ namespace vcpkg::PostBuildLint print2(Color::warning, "The following files are placed in\n", dir, ":\n"); print_paths(misplaced_files); print2(Color::warning, "Files cannot be present in those directories.\n\n"); - return LintStatus::ERROR_DETECTED; + return LintStatus::PROBLEM_DETECTED; } return LintStatus::SUCCESS; @@ -1025,8 +1078,13 @@ namespace vcpkg::PostBuildLint if (error_count != 0) { const auto portfile = port_dir / "portfile.cmake"; - print2( - Color::error, "Found ", error_count, " error(s). Please correct the portfile:\n ", portfile, "\n"); + print2(Color::error, + "Found ", + error_count, + " post-build check problem(s). To submit these ports to curated catalogs, please first correct the " + "portfile:\n ", + portfile, + "\n"); } print2("-- Performing post-build validation done\n"); diff --git a/src/vcpkg/vcpkgcmdarguments.cpp b/src/vcpkg/vcpkgcmdarguments.cpp index aa2f28f31..3857017ac 100644 --- a/src/vcpkg/vcpkgcmdarguments.cpp +++ b/src/vcpkg/vcpkgcmdarguments.cpp @@ -598,15 +598,24 @@ namespace vcpkg table.header("Options"); for (auto&& option : command_structure.options.switches) { - table.format(Strings::format("--%s", option.name), option.short_help_text); + if (option.short_help_text.size() != 0) + { + table.format(Strings::format("--%s", option.name), option.short_help_text); + } } for (auto&& option : command_structure.options.settings) { - table.format(Strings::format("--%s=...", option.name), option.short_help_text); + if (option.short_help_text.size() != 0) + { + table.format(Strings::format("--%s=...", option.name), option.short_help_text); + } } for (auto&& option : command_structure.options.multisettings) { - table.format(Strings::format("--%s=...", option.name), option.short_help_text); + if (option.short_help_text.size() != 0) + { + table.format(Strings::format("--%s=...", option.name), option.short_help_text); + } } VcpkgCmdArguments::append_common_options(table);