aboutsummaryrefslogtreecommitdiff
path: root/libbuild2/cc/link-rule.hxx
blob: 07e619da4bc41a74995a914c9e5180788c50061d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// file      : libbuild2/cc/link-rule.hxx -*- C++ -*-
// copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
// license   : MIT; see accompanying LICENSE file

#ifndef LIBBUILD2_CC_LINK_RULE_HXX
#define LIBBUILD2_CC_LINK_RULE_HXX

#include <set>

#include <libbuild2/types.hxx>
#include <libbuild2/utility.hxx>

#include <libbuild2/rule.hxx>

#include <libbuild2/cc/types.hxx>
#include <libbuild2/cc/common.hxx>

#include <libbuild2/cc/export.hxx>

namespace build2
{
  namespace cc
  {
    class LIBBUILD2_CC_SYMEXPORT link_rule: public rule, virtual common
    {
    public:
      link_rule (data&&);

      struct match_result
      {
        bool seen_x   = false;
        bool seen_c   = false;
        bool seen_cc  = false;
        bool seen_obj = false;
        bool seen_lib = false;
      };

      match_result
      match (action, const target&, const target*, otype, bool) const;

      virtual bool
      match (action, target&, const string&) const override;

      virtual recipe
      apply (action, target&) const override;

      target_state
      perform_update (action, const target&) const;

      target_state
      perform_clean (action, const target&) const;

    private:
      friend class install_rule;
      friend class libux_install_rule;

      // Shared library paths.
      //
      struct libs_paths
      {
        // If any (except real) is empty, then it is the same as the next
        // one. Except for load and intermediate, for which empty indicates
        // that it is not used.
        //
        // Note that the paths must form a "hierarchy" with subsequent paths
        // adding extra information as suffixes. This is relied upon by the
        // clean pattern (see below).
        //
        // The libs{} path is always the real path. On Windows what we link
        // to is the import library and the link path is empty.
        //
        path        link;   // What we link: libfoo.so
        path        load;   // What we load (with dlopen() or similar)
        path        soname; // SONAME:       libfoo-1.so, libfoo.so.1
        path        interm; // Intermediate: libfoo.so.1.2
        const path* real;   // Real:         libfoo.so.1.2.3

        inline const path&
        effect_link () const {return link.empty () ? effect_soname () : link;}

        inline const path&
        effect_soname () const {return soname.empty () ? *real : soname;}

        // Cleanup pattern used to remove previous versions. If empty, no
        // cleanup is performed. The above (current) names are automatically
        // filtered out.
        //
        path clean;
      };

      libs_paths
      derive_libs_paths (file&, const char*, const char*) const;

      struct match_data
      {
        // The "for install" condition is signalled to us by install_rule when
        // it is matched for the update operation. It also verifies that if we
        // have already been executed, then it was for install.
        //
        // This has an interesting implication: it means that this rule cannot
        // be used to update targets during match. Specifically, we cannot be
        // executed for group resolution purposes (not a problem) nor as part
        // of the generated source update. The latter case can be a problem:
        // imagine a code generator that itself may need to be updated before
        // it can be used to re-generate some out-of-date source code. As an
        // aside, note that even if we were somehow able to communicate the
        // "for install" in this case, the result of such an update may not
        // actually be "usable" (e.g., not runnable because of the missing
        // rpaths). There is another prominent case where the result may not
        // be usable: cross-compilation.
        //
        // So the current (admittedly fuzzy) thinking is that a project shall
        // not try to use its own build for update since it may not be usable
        // (because of cross-compilations, being "for install", etc). Instead,
        // it should rely on another, "usable" build of itself (this, BTW, is
        // related to bpkg's build-time vs run-time dependencies).
        //
        optional<bool> for_install;

        bool binless; // Binary-less library.
        size_t start; // Parallel prerequisites/prerequisite_targets start.

        link_rule::libs_paths libs_paths;
      };

      // Library handling.
      //
      void
      append_libraries (strings&,
                        const file&, bool, lflags,
                        const scope&, action, linfo) const;

      void
      append_libraries (sha256&,
                        bool&, timestamp,
                        const file&, bool, lflags,
                        const scope&, action, linfo) const;

      void
      rpath_libraries (strings&,
                       const target&,
                       const scope&, action, linfo,
                       bool) const;

      // Windows rpath emulation (windows-rpath.cxx).
      //
      struct windows_dll
      {
        const string& dll;
        const string* pdb; // NULL if none.
        string pdb_storage;

        bool operator< (const windows_dll& y) const {return dll < y.dll;}
      };

      using windows_dlls = std::set<windows_dll>;

      timestamp
      windows_rpath_timestamp (const file&,
                               const scope&,
                               action, linfo) const;

      windows_dlls
      windows_rpath_dlls (const file&, const scope&, action, linfo) const;

      void
      windows_rpath_assembly (const file&, const scope&, action, linfo,
                              const string&,
                              timestamp,
                              bool) const;

      // Windows-specific (windows-manifest.cxx).
      //
      pair<path, timestamp>
      windows_manifest (const file&, bool rpath_assembly) const;

      // pkg-config's .pc file generation (pkgconfig.cxx).
      //
      void
      pkgconfig_save (action, const file&, bool, bool) const;

    private:
      const string rule_id;
    };
  }
}

#endif // LIBBUILD2_CC_LINK_RULE_HXX