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-2021 by The D Language Foundation, All Rights Reserved
6  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
7  * License:     $(LINK2 http://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.errors;
20 import dmd.utils;
21 
22 import dmd.root.outbuffer;
23 import dmd.root.file;
24 import dmd.root.filename;
25 import dmd.root.string;
26 
27 static if (TARGET.Windows)
28 {
29     import dmd.libomf;
30     import dmd.libmscoff;
31 }
32 else static if (TARGET.Linux || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.Solaris || TARGET.DragonFlyBSD)
33 {
34     import dmd.libelf;
35 }
36 else static if (TARGET.OSX)
37 {
38     import dmd.libmach;
39 }
40 else
41 {
42     static assert(0, "unsupported system");
43 }
44 
45 private enum LOG = false;
46 
47 class Library
48 {
49     static Library factory()
50     {
51         static if (TARGET.Windows)
52         {
53             return (global.params.mscoff || global.params.is64bit) ? LibMSCoff_factory() : LibOMF_factory();
54         }
55         else static if (TARGET.Linux || TARGET.FreeBSD || TARGET.OpenBSD || TARGET.Solaris || TARGET.DragonFlyBSD)
56         {
57             return LibElf_factory();
58         }
59         else static if (TARGET.OSX)
60         {
61             return LibMach_factory();
62         }
63     }
64 
65     abstract void addObject(const(char)[] module_name, const ubyte[] buf);
66 
67     protected abstract void WriteLibToBuffer(OutBuffer* libbuf);
68 
69 
70     /***********************************
71      * Set the library file name based on the output directory
72      * and the filename.
73      * Add default library file name extension.
74      * Params:
75      *  dir = path to file
76      *  filename = name of file relative to `dir`
77      */
78     final void setFilename(const(char)[] dir, const(char)[] filename)
79     {
80         static if (LOG)
81         {
82             printf("LibElf::setFilename(dir = '%.*s', filename = '%.*s')\n",
83                    cast(int)dir.length, dir.ptr, cast(int)filename.length, filename.ptr);
84         }
85         const(char)[] arg = filename;
86         if (!arg.length)
87         {
88             // Generate lib file name from first obj name
89             const(char)[] n = global.params.objfiles[0].toDString;
90             n = FileName.name(n);
91             arg = FileName.forceExt(n, global.lib_ext);
92         }
93         if (!FileName.absolute(arg))
94             arg = FileName.combine(dir, arg);
95 
96         loc = Loc(FileName.defaultExt(arg, global.lib_ext).ptr, 0, 0);
97     }
98 
99     final const(char)* getFilename() const
100     {
101         return loc.filename;
102     }
103 
104     final void write()
105     {
106         if (global.params.verbose)
107             message("library   %s", loc.filename);
108 
109         OutBuffer libbuf;
110         WriteLibToBuffer(&libbuf);
111 
112         writeFile(Loc.initial, loc.filename.toDString, libbuf[]);
113     }
114 
115     final void error(const(char)* format, ...)
116     {
117         va_list ap;
118         va_start(ap, format);
119         .verror(loc, format, ap);
120         va_end(ap);
121     }
122 
123   protected:
124     Loc loc;                  // the filename of the library
125 }