diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2017-10-04 16:25:17 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-10-04 16:25:17 -0700 |
| commit | 875a1269be98971d492f0761e0ed3502957b5673 (patch) | |
| tree | 5d6748c384cb46f0df59ced1f7f8dab4bd983bea /toolsrc/src | |
| parent | 40d531e911618c6e2517d9646c39ad538fd0d352 (diff) | |
| parent | c98db7541594eadccf6823d4fdde2ff8c53c5fe9 (diff) | |
| download | vcpkg-875a1269be98971d492f0761e0ed3502957b5673.tar.gz vcpkg-875a1269be98971d492f0761e0ed3502957b5673.zip | |
Merge pull request #1734 from podsvirov/export-ifw
WIP: Export IFW (Beta)
Diffstat (limited to 'toolsrc/src')
| -rw-r--r-- | toolsrc/src/VcpkgPaths.cpp | 46 | ||||
| -rw-r--r-- | toolsrc/src/commands_export.cpp | 297 | ||||
| -rw-r--r-- | toolsrc/src/commands_export_ifw.cpp | 426 |
3 files changed, 670 insertions, 99 deletions
diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index cb00183fd..9f85992be 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -173,6 +173,34 @@ namespace vcpkg return fetch_dependency(scripts_folder, L"git", downloaded_copy, EXPECTED_VERSION); } + static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder) + { + static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 1, 81}; + static const std::wstring VERSION_CHECK_ARGUMENTS = L"--framework-version"; + + const fs::path downloaded_copy = + downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe"; + + std::vector<fs::path> candidate_paths; + candidate_paths.push_back(downloaded_copy); + // TODO: Uncomment later + // const std::vector<fs::path> from_path = Files::find_from_PATH(L"installerbase"); + // candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); + // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe"); + // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" / + // "QtIFW-3.1.0" / "bin" / "installerbase.exe"); + + const Optional<fs::path> path = + find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION); + if (const auto p = path.get()) + { + return *p; + } + + return fetch_dependency(scripts_folder, L"installerbase", downloaded_copy, EXPECTED_VERSION); + } + Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir) { std::error_code ec; @@ -256,6 +284,24 @@ namespace vcpkg return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); }); } + const fs::path& VcpkgPaths::get_ifw_installerbase_exe() const + { + return this->ifw_installerbase_exe.get_lazy( + [this]() { return get_ifw_installerbase_path(this->downloads, this->scripts); }); + } + + const fs::path& VcpkgPaths::get_ifw_binarycreator_exe() const + { + return this->ifw_binarycreator_exe.get_lazy( + [this]() { return get_ifw_installerbase_exe().parent_path() / "binarycreator.exe"; }); + } + + const fs::path& VcpkgPaths::get_ifw_repogen_exe() const + { + return this->ifw_repogen_exe.get_lazy( + [this]() { return get_ifw_installerbase_exe().parent_path() / "repogen.exe"; }); + } + static std::vector<std::string> get_vs2017_installation_instances(const VcpkgPaths& paths) { const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1"; diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp index b416a6f3c..20838f5a5 100644 --- a/toolsrc/src/commands_export.cpp +++ b/toolsrc/src/commands_export.cpp @@ -2,6 +2,7 @@ #include "Paragraphs.h" #include "vcpkg_Commands.h" +#include "vcpkg_Commands_Export_IFW.h" #include "vcpkg_Dependencies.h" #include "vcpkg_Input.h" #include "vcpkg_System.h" @@ -210,103 +211,168 @@ namespace vcpkg::Commands::Export return nullopt; } - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void export_integration_files(const fs::path& raw_exported_dir_path, const VcpkgPaths& paths) + { + const std::vector<fs::path> integration_files_relative_to_root = { + {".vcpkg-root"}, + {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"}, + {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"}, + {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, + {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, + {fs::path{"scripts"} / "getWindowsSDK.ps1"}, + {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, + {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, + }; + + for (const fs::path& file : integration_files_relative_to_root) + { + const fs::path source = paths.root / file; + fs::path destination = raw_exported_dir_path / file; + Files::Filesystem& fs = paths.get_filesystem(); + std::error_code ec; + fs.create_directories(destination.parent_path(), ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec); + fs.copy_file(source, destination, fs::copy_options::overwrite_existing, ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec); + } + } + + struct ExportArguments + { + bool dry_run; + bool raw; + bool nuget; + bool ifw; + bool zip; + bool seven_zip; + + Optional<std::string> maybe_nuget_id; + Optional<std::string> maybe_nuget_version; + + IFW::Options ifw_options; + std::vector<PackageSpec> specs; + }; + + static ExportArguments handle_export_command_arguments(const VcpkgCmdArguments& args, + const Triplet& default_triplet) { + ExportArguments ret; + static const std::string OPTION_DRY_RUN = "--dry-run"; static const std::string OPTION_RAW = "--raw"; static const std::string OPTION_NUGET = "--nuget"; + static const std::string OPTION_IFW = "--ifw"; static const std::string OPTION_ZIP = "--zip"; static const std::string OPTION_SEVEN_ZIP = "--7zip"; static const std::string OPTION_NUGET_ID = "--nuget-id"; static const std::string OPTION_NUGET_VERSION = "--nuget-version"; + static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url"; + static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path"; + static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path"; + static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path"; + static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path"; // input sanitization static const std::string EXAMPLE = Commands::Help::create_example_string("export zlib zlib:x64-windows boost --nuget"); args.check_min_arg_count(1, EXAMPLE); - const std::vector<PackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) { + ret.specs = Util::fmap(args.command_arguments, [&](auto&& arg) { return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE); }); - for (auto&& spec : specs) - Input::check_triplet(spec.triplet(), paths); const auto options = args.check_and_get_optional_command_arguments( { OPTION_DRY_RUN, OPTION_RAW, OPTION_NUGET, + OPTION_IFW, OPTION_ZIP, OPTION_SEVEN_ZIP, }, { OPTION_NUGET_ID, OPTION_NUGET_VERSION, + OPTION_IFW_REPOSITORY_URL, + OPTION_IFW_PACKAGES_DIR_PATH, + OPTION_IFW_REPOSITORY_DIR_PATH, + OPTION_IFW_CONFIG_FILE_PATH, + OPTION_IFW_INSTALLER_FILE_PATH, }); - const bool dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); - const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend(); - const bool nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); - const bool zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); - const bool seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); - - if (!raw && !nuget && !zip && !seven_zip && !dry_run) + ret.dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend(); + ret.raw = options.switches.find(OPTION_RAW) != options.switches.cend(); + ret.nuget = options.switches.find(OPTION_NUGET) != options.switches.cend(); + ret.ifw = options.switches.find(OPTION_IFW) != options.switches.cend(); + ret.zip = options.switches.find(OPTION_ZIP) != options.switches.cend(); + ret.seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend(); + + if (!ret.raw && !ret.nuget && !ret.ifw && !ret.zip && !ret.seven_zip && !ret.dry_run) { - System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --zip --7zip"); + System::println(System::Color::error, + "Must provide at least one export type: --raw --nuget --ifw --zip --7zip"); System::print(EXAMPLE); Checks::exit_fail(VCPKG_LINE_INFO); } - auto maybe_nuget_id = maybe_lookup(options.settings, OPTION_NUGET_ID); - auto maybe_nuget_version = maybe_lookup(options.settings, OPTION_NUGET_VERSION); - - Checks::check_exit(VCPKG_LINE_INFO, !maybe_nuget_id || nuget, "--nuget-id is only valid with --nuget"); - Checks::check_exit( - VCPKG_LINE_INFO, !maybe_nuget_version || nuget, "--nuget-version is only valid with --nuget"); - - // create the plan - const StatusParagraphs status_db = database_load_check(paths); - std::vector<ExportPlanAction> export_plan = Dependencies::create_export_plan(paths, specs, status_db); - Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); - - std::map<ExportPlanType, std::vector<const ExportPlanAction*>> group_by_plan_type; - Util::group_by(export_plan, &group_by_plan_type, [](const ExportPlanAction& p) { return p.plan_type; }); - print_plan(group_by_plan_type); - - const bool has_non_user_requested_packages = - Util::find_if(export_plan, [](const ExportPlanAction& package) -> bool { - return package.request_type != RequestType::USER_REQUESTED; - }) != export_plan.cend(); - - if (has_non_user_requested_packages) - { - System::println(System::Color::warning, - "Additional packages (*) need to be exported to complete this operation."); - } - - const auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT); - if (it != group_by_plan_type.cend() && !it->second.empty()) - { - System::println(System::Color::error, "There are packages that have not been built."); - - // No need to show all of them, just the user-requested ones. Dependency resolution will handle the rest. - std::vector<const ExportPlanAction*> unbuilt = it->second; - Util::erase_remove_if( - unbuilt, [](const ExportPlanAction* a) { return a->request_type != RequestType::USER_REQUESTED; }); - - const auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); }); - System::println("To build them, run:\n" - " vcpkg install %s", - s); - Checks::exit_fail(VCPKG_LINE_INFO); - } - - if (dry_run) + struct OptionPair { - Checks::exit_success(VCPKG_LINE_INFO); - } + const std::string& name; + Optional<std::string>& out_opt; + }; + const auto options_implies = + [&](const std::string& main_opt_name, bool main_opt, Span<const OptionPair> implying_opts) { + if (main_opt) + { + for (auto&& opt : implying_opts) + opt.out_opt = maybe_lookup(options.settings, opt.name); + } + else + { + for (auto&& opt : implying_opts) + Checks::check_exit(VCPKG_LINE_INFO, + !maybe_lookup(options.settings, opt.name), + "%s is only valid with %s", + opt.name, + main_opt_name); + } + }; + + options_implies(OPTION_NUGET, + ret.nuget, + { + {OPTION_NUGET_ID, ret.maybe_nuget_id}, + {OPTION_NUGET_VERSION, ret.maybe_nuget_version}, + }); + + options_implies(OPTION_IFW, + ret.ifw, + { + {OPTION_IFW_REPOSITORY_URL, ret.ifw_options.maybe_repository_url}, + {OPTION_IFW_PACKAGES_DIR_PATH, ret.ifw_options.maybe_packages_dir_path}, + {OPTION_IFW_REPOSITORY_DIR_PATH, ret.ifw_options.maybe_repository_dir_path}, + {OPTION_IFW_CONFIG_FILE_PATH, ret.ifw_options.maybe_config_file_path}, + {OPTION_IFW_INSTALLER_FILE_PATH, ret.ifw_options.maybe_installer_file_path}, + }); + return ret; + } - const std::string export_id = create_export_id(); + static void print_next_step_info(const fs::path& prefix) + { + const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; + const CMakeVariable cmake_variable = CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); + System::println("\n" + "To use the exported libraries in CMake projects use:" + "\n" + " %s" + "\n", + Strings::to_utf8(cmake_variable.s)); + }; + static void handle_raw_based_export(Span<const ExportPlanAction> export_plan, + const ExportArguments& opts, + const std::string& export_id, + const VcpkgPaths& paths) + { Files::Filesystem& fs = paths.get_filesystem(); const fs::path export_to_path = paths.root; const fs::path raw_exported_dir_path = export_to_path / export_id; @@ -327,6 +393,7 @@ namespace vcpkg::Commands::Export const BinaryParagraph& binary_paragraph = action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + const InstallDir dirs = InstallDir::from_destination_root( raw_exported_dir_path / "installed", action.spec.triplet().to_string(), @@ -337,52 +404,21 @@ namespace vcpkg::Commands::Export } // Copy files needed for integration - const std::vector<fs::path> integration_files_relative_to_root = { - {".vcpkg-root"}, - {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"}, - {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"}, - {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"}, - {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"}, - {fs::path{"scripts"} / "getWindowsSDK.ps1"}, - {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"}, - {fs::path{"scripts"} / "getProgramFiles32bit.ps1"}, - }; - - for (const fs::path& file : integration_files_relative_to_root) - { - const fs::path source = paths.root / file; - const fs::path destination = raw_exported_dir_path / file; - fs.create_directories(destination.parent_path(), ec); - Checks::check_exit(VCPKG_LINE_INFO, !ec); - fs.copy_file(source, destination, fs::copy_options::overwrite_existing, ec); - Checks::check_exit(VCPKG_LINE_INFO, !ec); - } + export_integration_files(raw_exported_dir_path, paths); - const auto print_next_step_info = [](const fs::path& prefix) { - const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake"; - const CMakeVariable cmake_variable = - CMakeVariable(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string()); - System::println("\n" - "To use the exported libraries in CMake projects use:" - "\n" - " %s" - "\n", - Strings::to_utf8(cmake_variable.s)); - }; - - if (raw) + if (opts.raw) { System::println( System::Color::success, R"(Files exported at: "%s")", raw_exported_dir_path.generic_string()); print_next_step_info(export_to_path); } - if (nuget) + if (opts.nuget) { System::println("Creating nuget package... "); - const std::string nuget_id = maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); - const std::string nuget_version = maybe_nuget_version.value_or("1.0.0"); + const std::string nuget_id = opts.maybe_nuget_id.value_or(raw_exported_dir_path.filename().string()); + const std::string nuget_version = opts.maybe_nuget_version.value_or("1.0.0"); const fs::path output_path = do_nuget_export(paths, nuget_id, nuget_version, raw_exported_dir_path, export_to_path); System::println(System::Color::success, "Creating nuget package... done"); @@ -397,7 +433,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console output_path.parent_path().u8string()); } - if (zip) + if (opts.zip) { System::println("Creating zip archive... "); const fs::path output_path = @@ -407,7 +443,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console print_next_step_info("[...]"); } - if (seven_zip) + if (opts.seven_zip) { System::println("Creating 7zip archive... "); const fs::path output_path = @@ -417,10 +453,73 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console print_next_step_info("[...]"); } - if (!raw) + if (!opts.raw) { fs.remove_all(raw_exported_dir_path, ec); } + } + + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + { + const auto opts = handle_export_command_arguments(args, default_triplet); + for (auto&& spec : opts.specs) + Input::check_triplet(spec.triplet(), paths); + + // create the plan + const StatusParagraphs status_db = database_load_check(paths); + std::vector<ExportPlanAction> export_plan = Dependencies::create_export_plan(paths, opts.specs, status_db); + Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty"); + + std::map<ExportPlanType, std::vector<const ExportPlanAction*>> group_by_plan_type; + Util::group_by(export_plan, &group_by_plan_type, [](const ExportPlanAction& p) { return p.plan_type; }); + print_plan(group_by_plan_type); + + const bool has_non_user_requested_packages = + Util::find_if(export_plan, [](const ExportPlanAction& package) -> bool { + return package.request_type != RequestType::USER_REQUESTED; + }) != export_plan.cend(); + + if (has_non_user_requested_packages) + { + System::println(System::Color::warning, + "Additional packages (*) need to be exported to complete this operation."); + } + + const auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT); + if (it != group_by_plan_type.cend() && !it->second.empty()) + { + System::println(System::Color::error, "There are packages that have not been built."); + + // No need to show all of them, just the user-requested ones. Dependency resolution will handle the rest. + std::vector<const ExportPlanAction*> unbuilt = it->second; + Util::erase_remove_if( + unbuilt, [](const ExportPlanAction* a) { return a->request_type != RequestType::USER_REQUESTED; }); + + const auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); }); + System::println("To build them, run:\n" + " vcpkg install %s", + s); + Checks::exit_fail(VCPKG_LINE_INFO); + } + + if (opts.dry_run) + { + Checks::exit_success(VCPKG_LINE_INFO); + } + + std::string export_id = create_export_id(); + + if (opts.raw || opts.nuget || opts.zip || opts.seven_zip) + { + handle_raw_based_export(export_plan, opts, export_id, paths); + } + + if (opts.ifw) + { + IFW::do_export(export_plan, export_id, opts.ifw_options, paths); + + print_next_step_info("@RootDir@/src/vcpkg"); + } Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/commands_export_ifw.cpp b/toolsrc/src/commands_export_ifw.cpp new file mode 100644 index 000000000..0dc8a7d31 --- /dev/null +++ b/toolsrc/src/commands_export_ifw.cpp @@ -0,0 +1,426 @@ +#include "pch.h" + +#include "vcpkg_Commands.h" +#include "vcpkg_Commands_Export.h" +#include "vcpkg_Commands_Export_IFW.h" + +namespace vcpkg::Commands::Export::IFW +{ + using Dependencies::ExportPlanAction; + using Dependencies::ExportPlanType; + using Install::InstallDir; + + static std::string create_release_date() + { + const tm date_time = System::get_current_date_time(); + + // Format is: YYYY-mm-dd + // 10 characters + 1 null terminating character will be written for a total of 11 chars + char mbstr[11]; + const size_t bytes_written = std::strftime(mbstr, sizeof(mbstr), "%Y-%m-%d", &date_time); + Checks::check_exit(VCPKG_LINE_INFO, + bytes_written == 10, + "Expected 10 bytes to be written, but %u were written", + bytes_written); + const std::string date_time_as_string(mbstr); + return date_time_as_string; + } + + fs::path get_packages_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_packages_dir_path.has_value() + ? fs::path(ifw_options.maybe_packages_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-packages"); + } + + fs::path get_repository_dir_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_repository_dir_path.has_value() + ? fs::path(ifw_options.maybe_repository_dir_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-repository"); + } + + fs::path get_config_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_config_file_path.has_value() + ? fs::path(ifw_options.maybe_config_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-configuration.xml"); + } + + fs::path get_installer_file_path(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + return ifw_options.maybe_installer_file_path.has_value() + ? fs::path(ifw_options.maybe_installer_file_path.value_or_exit(VCPKG_LINE_INFO)) + : paths.root / (export_id + "-ifw-installer.exe"); + } + + fs::path export_real_package(const fs::path& ifw_packages_dir_path, + const ExportPlanAction& action, + Files::Filesystem& fs) + { + std::error_code ec; + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + // Prepare meta dir + const fs::path package_xml_file_path = + ifw_packages_dir_path / + Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "meta" / + "package.xml"; + const fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + auto deps = Strings::join( + ",", binary_paragraph.depends, [](const std::string& dep) { return "packages." + dep + ":"; }); + + if (!deps.empty()) deps = "\n <Dependencies>" + deps + "</Dependencies>"; + + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>%s</DisplayName> + <Version>%s</Version> + <ReleaseDate>%s</ReleaseDate> + <AutoDependOn>packages.%s:,triplets.%s:</AutoDependOn>%s + <Virtual>true</Virtual> +</Package> +)###", + action.spec.to_string(), + binary_paragraph.version, + create_release_date(), + action.spec.name(), + action.spec.triplet().canonical_name(), + deps)); + + // Return dir path for export package data + return ifw_packages_dir_path / + Strings::format("packages.%s.%s", action.spec.name(), action.spec.triplet().canonical_name()) / "data" / + "installed"; + } + + void export_unique_packages(const fs::path& raw_exported_dir_path, + std::map<std::string, const ExportPlanAction*> unique_packages, + Files::Filesystem& fs) + { + std::error_code ec; + + // packages + + fs::path package_xml_file_path = raw_exported_dir_path / "packages" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>Packages</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + create_release_date())); + + for (auto package = unique_packages.begin(); package != unique_packages.end(); ++package) + { + const ExportPlanAction& action = *(package->second); + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + package_xml_file_path = + raw_exported_dir_path / Strings::format("packages.%s", package->first) / "meta" / "package.xml"; + package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>%s</DisplayName> + <Description>%s</Description> + <Version>%s</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + action.spec.name(), + binary_paragraph.description, + binary_paragraph.version, + create_release_date())); + } + } + + void export_unique_triplets(const fs::path& raw_exported_dir_path, + std::set<std::string> unique_triplets, + Files::Filesystem& fs) + { + std::error_code ec; + + // triplets + + fs::path package_xml_file_path = raw_exported_dir_path / "triplets" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>Triplets</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + create_release_date())); + + for (const std::string& triplet : unique_triplets) + { + package_xml_file_path = + raw_exported_dir_path / Strings::format("triplets.%s", triplet) / "meta" / "package.xml"; + package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>%s</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + triplet, + create_release_date())); + } + } + + void export_integration(const fs::path& raw_exported_dir_path, Files::Filesystem& fs) + { + std::error_code ec; + + // integration + fs::path package_xml_file_path = raw_exported_dir_path / "integration" / "meta" / "package.xml"; + fs::path package_xml_dir_path = package_xml_file_path.parent_path(); + fs.create_directories(package_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for package file %s", + package_xml_file_path.generic_string()); + + fs.write_contents(package_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Package> + <DisplayName>Integration</DisplayName> + <Version>1.0.0</Version> + <ReleaseDate>%s</ReleaseDate> +</Package> +)###", + create_release_date())); + } + + void export_config(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + const fs::path config_xml_file_path = get_config_file_path(export_id, ifw_options, paths); + + fs::path config_xml_dir_path = config_xml_file_path.parent_path(); + fs.create_directories(config_xml_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not create directory for configuration file %s", + config_xml_file_path.generic_string()); + + std::string formatted_repo_url; + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + formatted_repo_url = Strings::format(R"###( + <RemoteRepositories> + <Repository> + <Url>%s</Url> + </Repository> + </RemoteRepositories>)###", + ifw_repo_url); + } + + fs.write_contents(config_xml_file_path, + Strings::format( + R"###(<?xml version="1.0"?> +<Installer> + <Name>vcpkg</Name> + <Version>1.0.0</Version> + <TargetDir>@RootDir@/src/vcpkg</TargetDir>%s +</Installer> +)###", + formatted_repo_url)); + } + + void do_repository(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + const fs::path& repogen_exe = paths.get_ifw_repogen_exe(); + const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); + + System::println("Generating repository %s...", repository_dir.generic_string()); + + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + fs.remove_all(repository_dir, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not remove outdated repository directory %s", repository_dir.generic_string()); + + const std::wstring cmd_line = Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)", + repogen_exe.native(), + packages_dir.native(), + repository_dir.native()); + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW repository generating failed"); + + System::println(System::Color::success, "Generating repository %s... done.", repository_dir.generic_string()); + } + + void do_installer(const std::string& export_id, const Options& ifw_options, const VcpkgPaths& paths) + { + const fs::path& binarycreator_exe = paths.get_ifw_binarycreator_exe(); + const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); + const fs::path packages_dir = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path repository_dir = get_repository_dir_path(export_id, ifw_options, paths); + const fs::path installer_file = get_installer_file_path(export_id, ifw_options, paths); + + System::println("Generating installer %s...", installer_file.generic_string()); + + std::wstring cmd_line; + + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + cmd_line = Strings::wformat(LR"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + repository_dir.native(), + installer_file.native()); + } + else + { + cmd_line = Strings::wformat(LR"("%s" --config "%s" --packages "%s" "%s" > nul)", + binarycreator_exe.native(), + config_file.native(), + packages_dir.native(), + installer_file.native()); + } + + const int exit_code = System::cmd_execute_clean(cmd_line); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW installer generating failed"); + + System::println(System::Color::success, "Generating installer %s... done.", installer_file.generic_string()); + } + + void do_export(const std::vector<ExportPlanAction>& export_plan, + const std::string& export_id, + const Options& ifw_options, + const VcpkgPaths& paths) + { + const fs::path ifw_packages_dir_path = get_packages_dir_path(export_id, ifw_options, paths); + const fs::path config_file = get_config_file_path(export_id, ifw_options, paths); + + System::println("Exporting packages %s... ", ifw_packages_dir_path.generic_string()); + + std::error_code ec; + Files::Filesystem& fs = paths.get_filesystem(); + + fs.remove_all(ifw_packages_dir_path, ec); + Checks::check_exit(VCPKG_LINE_INFO, + !ec, + "Could not remove outdated packages directory %s", + ifw_packages_dir_path.generic_string()); + + fs.create_directory(ifw_packages_dir_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !ec, "Could not create packages directory %s", ifw_packages_dir_path.generic_string()); + + // execute the plan + std::map<std::string, const ExportPlanAction*> unique_packages; + std::set<std::string> unique_triplets; + for (const ExportPlanAction& action : export_plan) + { + if (action.plan_type != ExportPlanType::ALREADY_BUILT) + { + Checks::unreachable(VCPKG_LINE_INFO); + } + + const std::string display_name = action.spec.to_string(); + System::println("Exporting package %s... ", display_name); + + const BinaryParagraph& binary_paragraph = + action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph; + + unique_packages[action.spec.name()] = &action; + unique_triplets.insert(action.spec.triplet().canonical_name()); + + // Export real package and return data dir for installation + fs::path ifw_package_dir_path = export_real_package(ifw_packages_dir_path, action, fs); + + // Copy package data + const InstallDir dirs = InstallDir::from_destination_root(ifw_package_dir_path, + action.spec.triplet().to_string(), + ifw_package_dir_path / "vcpkg" / "info" / + (binary_paragraph.fullstem() + ".list")); + + Install::install_files_and_write_listfile(paths.get_filesystem(), paths.package_dir(action.spec), dirs); + System::println("Exporting package %s... done", display_name); + } + + System::println("Exporting packages %s... done", ifw_packages_dir_path.generic_string()); + + System::println("Generating configuration %s...", config_file.generic_string()); + + // Unique packages + export_unique_packages(ifw_packages_dir_path, unique_packages, fs); + + // Unique triplets + export_unique_triplets(ifw_packages_dir_path, unique_triplets, fs); + + // Copy files needed for integration + export_integration_files(ifw_packages_dir_path / "integration" / "data", paths); + // Integration + export_integration(ifw_packages_dir_path, fs); + + // Configuration + export_config(export_id, ifw_options, paths); + + System::println("Generating configuration %s... done.", config_file.generic_string()); + + // Do repository (optional) + std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or(""); + if (!ifw_repo_url.empty()) + { + do_repository(export_id, ifw_options, paths); + } + + // Do installer + do_installer(export_id, ifw_options, paths); + } +} |
