Skip to content

std, stage1: make shared library versioning optional #6315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 64 additions & 34 deletions lib/std/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,14 @@ pub const Builder = struct {
}));
}

pub fn addSharedLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8, ver: Version) *LibExeObjStep {
pub fn addSharedLibrary(
self: *Builder,
name: []const u8,
root_src: ?[]const u8,
kind: LibExeObjStep.SharedLibKind,
) *LibExeObjStep {
const root_src_param = if (root_src) |p| @as(FileSource, .{ .path = p }) else null;
return LibExeObjStep.createSharedLibrary(self, name, root_src_param, ver);
return LibExeObjStep.createSharedLibrary(self, name, root_src_param, kind);
}

pub fn addStaticLibrary(self: *Builder, name: []const u8, root_src: ?[]const u8) *LibExeObjStep {
Expand Down Expand Up @@ -338,11 +343,13 @@ pub const Builder = struct {
return TranslateCStep.create(self, source);
}

pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) Version {
return Version{
.major = major,
.minor = minor,
.patch = patch,
pub fn version(self: *const Builder, major: u32, minor: u32, patch: u32) LibExeObjStep.SharedLibKind {
return .{
.versioned = .{
.major = major,
.minor = minor,
.patch = patch,
},
};
}

Expand Down Expand Up @@ -1166,7 +1173,7 @@ pub const LibExeObjStep = struct {
version_script: ?[]const u8 = null,
out_filename: []const u8,
is_dynamic: bool,
version: Version,
version: ?Version,
build_mode: builtin.Mode,
kind: Kind,
major_only_filename: []const u8,
Expand Down Expand Up @@ -1268,33 +1275,41 @@ pub const LibExeObjStep = struct {
Test,
};

pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource, ver: Version) *LibExeObjStep {
const SharedLibKind = union(enum) {
versioned: Version,
unversioned: void,
};

pub fn createSharedLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource, kind: SharedLibKind) *LibExeObjStep {
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, ver);
self.* = initExtraArgs(builder, name, root_src, Kind.Lib, true, switch (kind) {
.versioned => |ver| ver,
.unversioned => null,
});
return self;
}

pub fn createStaticLibrary(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, builder.version(0, 0, 0));
self.* = initExtraArgs(builder, name, root_src, Kind.Lib, false, null);
return self;
}

pub fn createObject(builder: *Builder, name: []const u8, root_src: ?FileSource) *LibExeObjStep {
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0));
self.* = initExtraArgs(builder, name, root_src, Kind.Obj, false, null);
return self;
}

pub fn createExecutable(builder: *Builder, name: []const u8, root_src: ?FileSource, is_dynamic: bool) *LibExeObjStep {
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
self.* = initExtraArgs(builder, name, root_src, Kind.Exe, is_dynamic, builder.version(0, 0, 0));
self.* = initExtraArgs(builder, name, root_src, Kind.Exe, is_dynamic, null);
return self;
}

pub fn createTest(builder: *Builder, name: []const u8, root_src: FileSource) *LibExeObjStep {
const self = builder.allocator.create(LibExeObjStep) catch unreachable;
self.* = initExtraArgs(builder, name, root_src, Kind.Test, false, builder.version(0, 0, 0));
self.* = initExtraArgs(builder, name, root_src, Kind.Test, false, null);
return self;
}

Expand All @@ -1304,7 +1319,7 @@ pub const LibExeObjStep = struct {
root_src: ?FileSource,
kind: Kind,
is_dynamic: bool,
ver: Version,
ver: ?Version,
) LibExeObjStep {
if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) {
panic("invalid name: '{}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
Expand Down Expand Up @@ -1375,17 +1390,17 @@ pub const LibExeObjStep = struct {
self.target.staticLibSuffix(),
});
self.out_lib_filename = self.out_filename;
} else {
} else if (self.version) |version| {
if (self.target.isDarwin()) {
self.out_filename = self.builder.fmt("lib{}.{d}.{d}.{d}.dylib", .{
self.name,
self.version.major,
self.version.minor,
self.version.patch,
version.major,
version.minor,
version.patch,
});
self.major_only_filename = self.builder.fmt("lib{}.{d}.dylib", .{
self.name,
self.version.major,
version.major,
});
self.name_only_filename = self.builder.fmt("lib{}.dylib", .{self.name});
self.out_lib_filename = self.out_filename;
Expand All @@ -1395,14 +1410,25 @@ pub const LibExeObjStep = struct {
} else {
self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", .{
self.name,
self.version.major,
self.version.minor,
self.version.patch,
version.major,
version.minor,
version.patch,
});
self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, self.version.major });
self.major_only_filename = self.builder.fmt("lib{}.so.{d}", .{ self.name, version.major });
self.name_only_filename = self.builder.fmt("lib{}.so", .{self.name});
self.out_lib_filename = self.out_filename;
}
} else {
if (self.target.isDarwin()) {
self.out_filename = self.builder.fmt("lib{}.dylib", .{self.name});
self.out_lib_filename = self.out_filename;
} else if (self.target.isWindows()) {
self.out_filename = self.builder.fmt("{}.dll", .{self.name});
self.out_lib_filename = self.builder.fmt("{}.lib", .{self.name});
} else {
self.out_filename = self.builder.fmt("lib{}.so", .{self.name});
self.out_lib_filename = self.out_filename;
}
}
},
}
Expand Down Expand Up @@ -2037,14 +2063,16 @@ pub const LibExeObjStep = struct {
zig_args.append(self.name) catch unreachable;

if (self.kind == Kind.Lib and self.is_dynamic) {
zig_args.append("--ver-major") catch unreachable;
zig_args.append(builder.fmt("{}", .{self.version.major})) catch unreachable;
if (self.version) |version| {
zig_args.append("--ver-major") catch unreachable;
zig_args.append(builder.fmt("{}", .{version.major})) catch unreachable;

zig_args.append("--ver-minor") catch unreachable;
zig_args.append(builder.fmt("{}", .{self.version.minor})) catch unreachable;
zig_args.append("--ver-minor") catch unreachable;
zig_args.append(builder.fmt("{}", .{version.minor})) catch unreachable;

zig_args.append("--ver-patch") catch unreachable;
zig_args.append(builder.fmt("{}", .{self.version.patch})) catch unreachable;
zig_args.append("--ver-patch") catch unreachable;
zig_args.append(builder.fmt("{}", .{version.patch})) catch unreachable;
}
}
if (self.is_dynamic) {
try zig_args.append("-dynamic");
Expand Down Expand Up @@ -2285,7 +2313,7 @@ pub const LibExeObjStep = struct {
}
}

if (self.kind == Kind.Lib and self.is_dynamic and self.target.wantSharedLibSymLinks()) {
if (self.kind == Kind.Lib and self.is_dynamic and self.version != null and self.target.wantSharedLibSymLinks()) {
try doAtomicSymLinks(builder.allocator, self.getOutputPath(), self.major_only_filename, self.name_only_filename);
}
}
Expand Down Expand Up @@ -2329,8 +2357,10 @@ pub const InstallArtifactStep = struct {

builder.pushInstalledFile(self.dest_dir, artifact.out_filename);
if (self.artifact.isDynamicLibrary()) {
builder.pushInstalledFile(.Lib, artifact.major_only_filename);
builder.pushInstalledFile(.Lib, artifact.name_only_filename);
if (self.artifact.version != null) {
builder.pushInstalledFile(.Lib, artifact.major_only_filename);
builder.pushInstalledFile(.Lib, artifact.name_only_filename);
}
if (self.artifact.target.isWindows()) {
builder.pushInstalledFile(.Lib, artifact.out_lib_filename);
}
Expand All @@ -2350,7 +2380,7 @@ pub const InstallArtifactStep = struct {

const full_dest_path = builder.getInstallPath(self.dest_dir, self.artifact.out_filename);
try builder.updateFile(self.artifact.getOutputPath(), full_dest_path);
if (self.artifact.isDynamicLibrary() and self.artifact.target.wantSharedLibSymLinks()) {
if (self.artifact.isDynamicLibrary() and self.artifact.version != null and self.artifact.target.wantSharedLibSymLinks()) {
try doAtomicSymLinks(builder.allocator, full_dest_path, self.artifact.major_only_filename, self.artifact.name_only_filename);
}
if (self.pdb_dir) |pdb_dir| {
Expand Down
1 change: 1 addition & 0 deletions src/all_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2265,6 +2265,7 @@ struct CodeGen {

Stage2LibCInstallation *libc;

bool is_versioned;
size_t version_major;
size_t version_minor;
size_t version_patch;
Expand Down
6 changes: 4 additions & 2 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix) {
g->test_name_prefix = prefix;
}

void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch) {
void codegen_set_lib_version(CodeGen *g, bool is_versioned, size_t major, size_t minor, size_t patch) {
g->is_versioned = is_versioned;
g->version_major = major;
g->version_minor = minor;
g->version_patch = patch;
Expand Down Expand Up @@ -10823,6 +10824,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_bool(ch, g->emit_bin);
cache_bool(ch, g->emit_llvm_ir);
cache_bool(ch, g->emit_asm);
cache_bool(ch, g->is_versioned);
cache_usize(ch, g->version_major);
cache_usize(ch, g->version_minor);
cache_usize(ch, g->version_patch);
Expand Down Expand Up @@ -10893,7 +10895,7 @@ static void resolve_out_paths(CodeGen *g) {
buf_resize(out_basename, 0);
buf_append_str(out_basename, target_lib_file_prefix(g->zig_target));
buf_append_buf(out_basename, g->root_out_name);
buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic,
buf_append_str(out_basename, target_lib_file_ext(g->zig_target, !g->is_dynamic, g->is_versioned,
g->version_major, g->version_minor, g->version_patch));
break;
}
Expand Down
2 changes: 1 addition & 1 deletion src/codegen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic);
void codegen_set_linker_script(CodeGen *g, const char *linker_script);
void codegen_set_test_filter(CodeGen *g, Buf *filter);
void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
void codegen_set_lib_version(CodeGen *g, bool is_versioned, size_t major, size_t minor, size_t patch);
void codegen_add_time_event(CodeGen *g, const char *name);
void codegen_print_timing_report(CodeGen *g, FILE *f);
void codegen_link(CodeGen *g);
Expand Down
2 changes: 1 addition & 1 deletion src/glibc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con
bool is_ld = (strcmp(lib->name, "ld") == 0);

CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr, lib->name, progress_node);
codegen_set_lib_version(child_gen, lib->sover, 0, 0);
codegen_set_lib_version(child_gen, true, lib->sover, 0, 0);
child_gen->is_dynamic = true;
child_gen->is_dummy_so = true;
child_gen->version_script_path = map_file_path;
Expand Down
8 changes: 7 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ static int main0(int argc, char **argv) {
const char *test_filter = nullptr;
const char *test_name_prefix = nullptr;
bool test_evented_io = false;
bool is_versioned = false;
size_t ver_major = 0;
size_t ver_minor = 0;
size_t ver_patch = 0;
Expand Down Expand Up @@ -870,13 +871,15 @@ static int main0(int argc, char **argv) {
fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
return EXIT_FAILURE;
}
is_versioned = true;
ver_major = atoi(buf_ptr(linker_args.at(i)));
} else if (buf_eql_str(arg, "--minor-image-version")) {
i += 1;
if (i >= linker_args.length) {
fprintf(stderr, "expected linker arg after '%s'\n", buf_ptr(arg));
return EXIT_FAILURE;
}
is_versioned = true;
ver_minor = atoi(buf_ptr(linker_args.at(i)));
} else if (buf_eql_str(arg, "--stack")) {
i += 1;
Expand Down Expand Up @@ -1228,10 +1231,13 @@ static int main0(int argc, char **argv) {
} else if (strcmp(arg, "--test-name-prefix") == 0) {
test_name_prefix = argv[i];
} else if (strcmp(arg, "--ver-major") == 0) {
is_versioned = true;
ver_major = atoi(argv[i]);
} else if (strcmp(arg, "--ver-minor") == 0) {
is_versioned = true;
ver_minor = atoi(argv[i]);
} else if (strcmp(arg, "--ver-patch") == 0) {
is_versioned = true;
ver_patch = atoi(argv[i]);
} else if (strcmp(arg, "--test-cmd") == 0) {
test_exec_args.append(argv[i]);
Expand Down Expand Up @@ -1590,7 +1596,7 @@ static int main0(int argc, char **argv) {
g->emit_llvm_ir = emit_llvm_ir;

codegen_set_out_name(g, buf_out_name);
codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
codegen_set_lib_version(g, is_versioned, ver_major, ver_minor, ver_patch);
g->want_single_threaded = want_single_threaded;
codegen_set_linker_script(g, linker_script);
g->version_script_path = version_script;
Expand Down
18 changes: 13 additions & 5 deletions src/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,7 @@ const char *target_lib_file_prefix(const ZigTarget *target) {
}
}

const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
const char *target_lib_file_ext(const ZigTarget *target, bool is_static, bool is_versioned,
size_t version_major, size_t version_minor, size_t version_patch)
{
if (target_is_wasm(target)) {
Expand All @@ -799,11 +799,19 @@ const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
if (is_static) {
return ".a";
} else if (target_os_is_darwin(target->os)) {
return buf_ptr(buf_sprintf(".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
version_major, version_minor, version_patch));
if (is_versioned) {
return buf_ptr(buf_sprintf(".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
version_major, version_minor, version_patch));
} else {
return ".dylib";
}
} else {
return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize,
version_major, version_minor, version_patch));
if (is_versioned) {
return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize,
version_major, version_minor, version_patch));
} else {
return ".so";
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/target.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const char *target_asm_file_ext(const ZigTarget *target);
const char *target_llvm_ir_file_ext(const ZigTarget *target);
const char *target_exe_file_ext(const ZigTarget *target);
const char *target_lib_file_prefix(const ZigTarget *target);
const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
const char *target_lib_file_ext(const ZigTarget *target, bool is_static, bool is_versioned,
size_t version_major, size_t version_minor, size_t version_patch);

bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
Expand Down