ide: developing vcpkg support

This commit is contained in:
Mirek Fidler 2026-08-12 00:18:18 +02:00
parent f99920247f
commit 6d486315ea
13 changed files with 225 additions and 5 deletions

View file

@ -459,6 +459,7 @@ public:
Array<OptItem> option;
Array<OptItem> include;
Array<OptItem> pkg_config;
Array<OptItem> external_dependency;
Array<File> file;
Array<Config> config;
Array<CustomStep> custom;
@ -707,4 +708,19 @@ String CleanupPretty(const String& signature);
Vector<ItemTextPart> ParsePretty(const String& name, const String& signature, int *fn_info = NULL);
struct VcpkgInstalled : Moveable<VcpkgInstalled> {
String name;
Index<String> triplets;
String version;
String desc;
};
bool IsVcpkgInstalled();
bool InstallVcpkg(Function<int(const String&, const String& chdir)> sys);
String VcpkgExe();
Vector<VcpkgInstalled> VcpkgList();
Vector<String> RequiredExternalDependencies(const String& manager);
Vector<String> VcpkgTriplets();
bool VcpkgHasInstalled(Vector<VcpkgInstalled>& items, const String& name, const String& triplet);
#endif

View file

@ -21,6 +21,7 @@ file
usc.cpp,
BinObj.cpp,
Signature.cpp,
Vcpkg.cpp,
Host readonly separator,
Host.h,
Host.cpp,

View file

@ -226,6 +226,7 @@ bool Package::Load(const char *path)
uses.Clear();
include.Clear();
pkg_config.Clear();
external_dependency.Clear();
accepts.Clear();
file.Clear();
config.Clear();
@ -248,7 +249,8 @@ bool Package::Load(const char *path)
!LoadOpt(p, "target", target) &&
!LoadOpt(p, "uses", uses) &&
!LoadOpt(p, "include", include) &&
!LoadOpt(p, "pkg_config", pkg_config)) {
!LoadOpt(p, "pkg_config", pkg_config) &&
!LoadOpt(p, "external_dependency", external_dependency)) {
if(p.Id("charset"))
charset = CharsetByNameX(p.ReadString());
else
@ -482,6 +484,8 @@ bool Package::Save(const char *path) const {
putopt(out, "link", link);
putopt(out, "include", include);
putopt(out, "pkg_config", pkg_config);
putopt(out, "external_dependency", external_dependency);
if(file.GetCount()) {
out << "file\n";
int i;

81
uppsrc/ide/Core/Vcpkg.cpp Normal file
View file

@ -0,0 +1,81 @@
#include "Core.h"
String VcpkgExe()
{
return GetExeFolder() + "/vcpkg/vcpkg.exe";
}
bool IsVcpkgInstalled()
{
return FileExists(VcpkgExe());
}
bool InstallVcpkg(Function<int(const String&, const String& chdir)> sys)
{
String exedir = GetExeFolder();
return sys("git clone https://github.com/microsoft/vcpkg.git", exedir) == 0 &&
sys("cmd /c \"" + exedir + "/vcpkg/bootstrap-vcpkg.bat\"", Null) == 0;
}
Vector<VcpkgInstalled> VcpkgList()
{
VectorMap<String, VcpkgInstalled> ms;
for(Value l : ParseJSON(Sys(VcpkgExe() + " list --x-json"))) {
String name = ~l["package_name"];
VcpkgInstalled& m = ms.GetAdd(name);
m.name = name;
m.triplets.FindAdd(~l["triplet"]);
m.version = ~l["version"];
String p = ~l["port_version"];
if(p != "0")
m.version << '#' << p;
if(l["desc"].GetCount())
m.desc = l["desc"][0];
}
return ms.PickValues();
}
Vector<String> RequiredExternalDependencies(const String& manager)
{
Vector<String> required;
const Workspace& wspc = GetIdeWorkspace();
for(int i = 0; i < wspc.GetCount(); i++) {
const Package& pkg = wspc.GetPackage(i);
for(const OptItem& m : pkg.external_dependency) {
if(IsNull(m.when) || m.when == manager)
required.Add(m.text);
}
}
Sort(required);
return required;
}
Vector<String> VcpkgTriplets()
{
Index<String> ts;
for(FindFile ff(ConfigFile("*.bm")); ff; ff.Next()) {
VectorMap<String, String> vars;
String fn = ConfigFile(ff.GetName());
if(LoadVarFile(fn, vars)) {
String builder = vars.Get("BUILDER", Null);
String compiler = vars.Get("COMPILER", Null);
if(builder == "CLANG")
ts.FindAdd(compiler.Find("i686") >= 0 ? "x86-mingw-static-release" : "x64-mingw-static-release");
if(builder.StartsWith("MSC"))
ts.FindAdd(builder.Find("64") >= 0 ? "x64-windows-static-md" : "x86-windows-static-md");
}
}
Vector<String> triplets = ts.PickKeys();
Sort(triplets);
return triplets;
}
bool VcpkgHasInstalled(Vector<VcpkgInstalled>& items, const String& name, const String& triplet)
{
for(const VcpkgInstalled& m : items)
if(m.name == name && m.triplets.Find(triplet) >= 0)
return true;
return false;
}

View file

@ -658,6 +658,7 @@ PackageEditor::PackageEditor()
Add("Compiler options", actual.option);
Add("Internal includes", actual.include);
Add("pkg-config", actual.pkg_config);
Add("External dependency", actual.external_dependency);
Init(option);
option.WhenCursor = THISBACK(AdjustPackageOptionCursor);

View file

@ -49,7 +49,7 @@ void UrepoConsole::Log(const Value& s, Color ink)
list.Add(AttrText(s).SetFont(font).NormalInk(ink), s);
}
int UrepoConsole::System(const char *cmd)
int UrepoConsole::System(const char *cmd, const char *chdir)
{
if(!IsOpen())
Open();
@ -67,6 +67,8 @@ int UrepoConsole::System(const char *cmd)
return -1;
Host host;
ide->CreateHost(host, false, false);
if(chdir)
host.ChDir(chdir);
LocalProcess p;
if(!host.StartProcess(p, cmd)) {
list.Add(AttrText("Failed to start the executable").SetFont(font().Bold()).Ink(SLtRed()));

View file

@ -438,8 +438,8 @@ struct PackageEditor : WorkspaceWork, WithUppLayout<TopWindow> {
virtual void PackageCursor();
enum OptionType {
FLAG = 0, USES, TARGET, LIBRARY, STATIC_LIBRARY, LINK, COMPILER, INCLUDE, PKG_CONFIG,
PKG_LAST = PKG_CONFIG,
FLAG = 0, USES, TARGET, LIBRARY, STATIC_LIBRARY, LINK, COMPILER, INCLUDE, PKG_CONFIG, EXTERNAL_DEPENDENCY,
PKG_LAST = EXTERNAL_DEPENDENCY,
FILEOPTION, FILEDEPENDS
};

View file

@ -1004,6 +1004,7 @@ public:
void DoMacroManager();
void UpgradeTheIDE();
void InstallDesktop();
void Vcpkg();
void SetupMobilePlatforms(Bar& bar);
void SetupAndroidMobilePlatform(Bar& bar, const AndroidSDK& androidSDK);

View file

@ -1039,3 +1039,12 @@ LAYOUT(ClangTidyLayout, 624, 580)
ITEM(Upp::Button, cancel, SetLabel(t_("Cancel")).RightPosZ(8, 64).BottomPosZ(8, 24))
END_LAYOUT
LAYOUT(VcpkgLayout, 1000, 700)
ITEM(Upp::ArrayCtrl, list, LeftPosZ(4, 992).TopPosZ(4, 468))
ITEM(Upp::Button, exit, SetLabel(t_("Close")).RightPosZ(8, 64).BottomPosZ(8, 24))
ITEM(Upp::Button, install_missing, SetLabel(t_("Install missing")).RightPosZ(564, 120).BottomPosZ(8, 24))
ITEM(Upp::ArrayCtrl, required_list, LeftPosZ(4, 150).TopPosZ(476, 188))
ITEM(Upp::ArrayCtrl, triplets_list, LeftPosZ(160, 150).TopPosZ(476, 188))
ITEM(Upp::ArrayCtrl, missing_list, LeftPosZ(316, 368).TopPosZ(476, 188))
END_LAYOUT

View file

@ -92,6 +92,7 @@ file
SetupGIT.cpp,
Upgrade.cpp,
UppHub.cpp,
vcpkg.cpp,
Compile readonly separator,
MethodsCtrls.h,
MethodsCtrls.cpp,

View file

@ -474,6 +474,10 @@ void Ide::Setup(Bar& menu)
menu.Add("Install theide.desktop", [=] { InstallDesktop(); });
#endif
#ifdef PLATFORM_WIN32
menu.Add("Vcpkg..", [=] { Vcpkg(); });
#endif
if(menu.IsMenuBar())
SetupMobilePlatforms(menu);
}

View file

@ -9,7 +9,7 @@ class UrepoConsole : public WithUrepoConsoleLayout<TopWindow> {
int hide_password_to = 0;
public:
int System(const char *s);
int System(const char *s, const char *chdir = nullptr);
int CheckSystem(const char *s);
int Git(const char *dir, const char *command, bool pwd = false);
void HidePassword(int from, int to) { hide_password_from = from; hide_password_to = to; }

100
uppsrc/ide/vcpkg.cpp Normal file
View file

@ -0,0 +1,100 @@
#include "ide.h"
#ifdef PLATFORM_WIN32
struct VcpkgDlg : WithVcpkgLayout<TopWindow> {
Vector<VcpkgInstalled> items;
void SyncIde();
void SyncList();
void Perform();
VcpkgDlg();
};
void VcpkgDlg::SyncIde()
{
Vector<String> triplets = VcpkgTriplets();
triplets_list.Clear();
for(String s : triplets)
triplets_list.Add(s);
Vector<String> required = RequiredExternalDependencies("VCPKG");
required_list.Clear();
for(String s : required)
required_list.Add(s);
for(String r : required)
for(String t : triplets)
if(!VcpkgHasInstalled(items, r, t))
missing_list.Add(r, t);
install_missing.Enable(missing_list.GetCount());
}
void VcpkgDlg::SyncList()
{
items = VcpkgList();
list.Clear();
for(const VcpkgInstalled& m : items)
list.Add(m.name, Join(m.triplets.GetKeys(), " "), m.version, m.desc);
}
void VcpkgDlg::Perform()
{
if(!IsVcpkgInstalled()) {
if(!PromptYesNo("Install vcpkg?"))
return;
UrepoConsole console;
if(!InstallVcpkg([&](const String& cmd, const String& chdir) { return console.System(cmd, chdir); })) {
Exclamation("Installation failed");
return;
}
console.Log("Installation completed.", SGreen());
console.Perform();
}
SyncList();
SyncIde();
Execute();
}
VcpkgDlg::VcpkgDlg()
{
CtrlLayoutExit(*this, "vcpkg");
list.AddColumn("Name");
list.AddColumn("Triplets");
list.AddColumn("Version");
list.AddColumn("Description");
list.ColumnWidths("140 396 79 281");
required_list.AddColumn("Required");
triplets_list.AddColumn("Triplets");
missing_list.AddColumn("Missing");
missing_list.AddColumn("Triplet");
install_missing << [=] {
UrepoConsole console;
for(int i = 0; i < missing_list.GetCount(); i++) {
String name = missing_list.Get(i, 0);
String triplet = missing_list.Get(i, 1);
console.System(VcpkgExe() + " install " + name + ":" + triplet);
}
console.Log("Installation completed.", SGreen());
console.Perform();
SyncList();
SyncIde();
};
}
void Ide::Vcpkg()
{
VcpkgDlg dlg;
dlg.Perform();
}
#endif