1 /** 2 * A module defining an abstract library. 3 * Implementations for various formats are in separate `libXXX.d` modules. 4 * 5 * Copyright: Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved 6 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/lib.d, _lib.d) 9 * Documentation: https://dlang.org/phobos/dmd_lib.html 10 * Coverage: https://codecov.io/gh/dlang/dmd/src/master/src/dmd/lib.d 11 */ 12 13 module dmd.lib; 14 15 import core.stdc.stdio; 16 import core.stdc.stdarg; 17 18 import dmd.globals; 19 import dmd.location; 20 import dmd.errors; 21 import dmd.target; 22 import dmd.utils; 23 24 import dmd.common.outbuffer; 25 import dmd.root.file; 26 import dmd.root.filename; 27 import dmd.root.string; 28 29 import dmd.libomf; 30 import dmd.libmscoff; 31 import dmd.libelf; 32 import dmd.libmach; 33 34 private enum LOG = false; 35 36 class Library 37 { 38 static Library factory() 39 { 40 final switch (target.objectFormat()) 41 { 42 case Target.ObjectFormat.elf: return LibElf_factory(); 43 case Target.ObjectFormat.macho: return LibMach_factory(); 44 case Target.ObjectFormat.coff: return LibMSCoff_factory(); 45 case Target.ObjectFormat.omf: return LibOMF_factory(); 46 } 47 } 48 49 abstract void addObject(const(char)[] module_name, const ubyte[] buf); 50 51 protected abstract void WriteLibToBuffer(OutBuffer* libbuf); 52 53 54 /*********************************** 55 * Set the library file name based on the output directory 56 * and the filename. 57 * Add default library file name extension. 58 * Params: 59 * dir = path to file 60 * filename = name of file relative to `dir` 61 */ 62 final void setFilename(const(char)[] dir, const(char)[] filename) 63 { 64 static if (LOG) 65 { 66 printf("LibElf::setFilename(dir = '%.*s', filename = '%.*s')\n", 67 cast(int)dir.length, dir.ptr, cast(int)filename.length, filename.ptr); 68 } 69 const(char)[] arg = filename; 70 if (!arg.length) 71 { 72 // Generate lib file name from first obj name 73 const(char)[] n = global.params.objfiles[0].toDString; 74 n = FileName.name(n); 75 arg = FileName.forceExt(n, target.lib_ext); 76 } 77 if (!FileName.absolute(arg)) 78 arg = FileName.combine(dir, arg); 79 80 loc = Loc(FileName.defaultExt(arg, target.lib_ext).ptr, 0, 0); 81 } 82 83 final const(char)* getFilename() const 84 { 85 return loc.filename; 86 } 87 88 final void write() 89 { 90 if (global.params.verbose) 91 message("library %s", loc.filename); 92 93 auto filenameString = loc.filename.toDString; 94 ensurePathToNameExists(Loc.initial, filenameString); 95 auto tmpname = filenameString ~ ".tmp\0"; 96 scope(exit) destroy(tmpname); 97 98 auto libbuf = OutBuffer(tmpname.ptr); 99 WriteLibToBuffer(&libbuf); 100 101 if (!libbuf.moveToFile(loc.filename)) 102 { 103 .error(loc, "error writing file '%s'", loc.filename); 104 fatal(); 105 } 106 } 107 108 final void error(const(char)* format, ...) 109 { 110 va_list ap; 111 va_start(ap, format); 112 .verror(loc, format, ap); 113 va_end(ap); 114 } 115 116 protected: 117 Loc loc; // the filename of the library 118 }