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 }