build: initial support for using vcpkg libraries

master
Sahnvour 2019-10-10 21:58:47 +02:00
parent 8c8078513e
commit def5462d05
2 changed files with 115 additions and 1 deletions

View File

@ -53,7 +53,7 @@ pub const Builder = struct {
release_mode: ?builtin.Mode,
is_release: bool,
override_lib_dir: ?[]const u8,
vcpkg_root: VcpkgRoot,
pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null,
const PkgConfigError = error{
@ -159,6 +159,7 @@ pub const Builder = struct {
.is_release = false,
.override_lib_dir = null,
.install_path = undefined,
.vcpkg_root = VcpkgRoot{ .Unattempted = {} },
};
try self.top_level_steps.append(&self.install_tls);
try self.top_level_steps.append(&self.uninstall_tls);
@ -1046,6 +1047,7 @@ pub const LibExeObjStep = struct {
output_dir: ?[]const u8,
need_system_paths: bool,
is_linking_libc: bool = false,
vcpkg_bin_path: ?[]const u8 = null,
installed_path: ?[]const u8,
install_step: ?*InstallArtifactStep,
@ -1264,6 +1266,11 @@ pub const LibExeObjStep = struct {
// option is supplied.
const run_step = RunStep.create(exe.builder, exe.builder.fmt("run {}", exe.step.name));
run_step.addArtifactArg(exe);
if (exe.vcpkg_bin_path) |path| {
run_step.addPathDir(path);
}
return run_step;
}
@ -1569,6 +1576,43 @@ pub const LibExeObjStep = struct {
}) catch unreachable;
}
/// If Vcpkg was found on the system, it will be added to include and lib
/// paths for the specified target.
pub fn addVcpkgPaths(self: *LibExeObjStep, linkage: VcpkgLinkage) !void {
// Ideally in the Unattempted case we would call the function recursively
// after findVcpkgRoot and have only one switch statement, but the compiler
// cannot resolve the error set.
switch (self.builder.vcpkg_root) {
.Unattempted => {
self.builder.vcpkg_root = if (try findVcpkgRoot(self.builder.allocator)) |root|
VcpkgRoot{ .Found = root }
else
.NotFound;
},
.NotFound => return error.VcpkgNotFound,
.Found => {},
}
switch (self.builder.vcpkg_root) {
.Unattempted => unreachable,
.NotFound => return error.VcpkgNotFound,
.Found => |root| {
const allocator = self.builder.allocator;
const triplet = try Target.vcpkgTriplet(allocator, self.target, linkage);
defer self.builder.allocator.free(triplet);
const include_path = try fs.path.join(allocator, [_][]const u8{ root, "installed", triplet, "include" });
errdefer allocator.free(include_path);
try self.include_dirs.append(IncludeDir{ .RawPath = include_path });
const lib_path = try fs.path.join(allocator, [_][]const u8{ root, "installed", triplet, "lib" });
try self.lib_paths.append(lib_path);
self.vcpkg_bin_path = try fs.path.join(allocator, [_][]const u8{ root, "installed", triplet, "bin" });
},
}
}
pub fn setExecCmd(self: *LibExeObjStep, args: []const ?[]const u8) void {
assert(self.kind == Kind.Test);
self.exec_cmd_args = args;
@ -2341,6 +2385,42 @@ fn doAtomicSymLinks(allocator: *Allocator, output_path: []const u8, filename_maj
};
}
/// Returned slice must be freed by the caller.
fn findVcpkgRoot(allocator: *Allocator) !?[]const u8 {
const appdata_path = try fs.getAppDataDir(allocator, "vcpkg");
defer allocator.free(appdata_path);
const path_file = try fs.path.join(allocator, [_][]const u8{ appdata_path, "vcpkg.path.txt" });
defer allocator.free(path_file);
const file = fs.File.openRead(path_file) catch return null;
defer file.close();
const size = @intCast(usize, try file.getEndPos());
const vcpkg_path = try allocator.alloc(u8, size);
const size_read = try file.read(vcpkg_path);
std.debug.assert(size == size_read);
return vcpkg_path;
}
const VcpkgRoot = union(VcpkgRootStatus) {
Unattempted: void,
NotFound: void,
Found: []const u8,
};
const VcpkgRootStatus = enum {
Unattempted,
NotFound,
Found,
};
pub const VcpkgLinkage = enum {
Static,
Dynamic,
};
pub const InstallDir = enum {
Prefix,
Lib,

View File

@ -218,6 +218,40 @@ pub const Target = union(enum) {
);
}
/// Returned slice must be freed by the caller.
pub fn vcpkgTriplet(allocator: *mem.Allocator, target: Target, linkage: std.build.VcpkgLinkage) ![]const u8 {
const arch = switch (target.getArch()) {
.i386 => "x86",
.x86_64 => "x64",
.arm,
.armeb,
.thumb,
.thumbeb,
.aarch64_32,
=> "arm",
.aarch64,
.aarch64_be,
=> "arm64",
else => return error.VcpkgNoSuchArchitecture,
};
const os = switch (target.getOs()) {
.windows => "windows",
.linux => "linux",
.macosx => "macos",
else => return error.VcpkgNoSuchOs,
};
if (linkage == .Static) {
return try mem.join(allocator, "-", [_][]const u8{ arch, os, "static" });
} else {
return try mem.join(allocator, "-", [_][]const u8{ arch, os });
}
}
pub fn allocDescription(self: Target, allocator: *mem.Allocator) ![]u8 {
// TODO is there anything else worthy of the description that is not
// already captured in the triple?