1 |
Sorry for the length of this but you really need to consider the bigger |
2 |
picture with this stuff and not all devs are familiar with it. |
3 |
|
4 |
For EAPI 7, mgorny and I are seeking to address some cross-compiling |
5 |
issues. This is a subject I've long had an interest in and before I |
6 |
became a developer, I created a project called cross-boss that, to be |
7 |
blunt, hacks its way through the shortcomings in Portage and the tree. |
8 |
It does (or at least did when I last worked on it) achieve a higher |
9 |
success rate than you would get from crossdev alone and allows you to |
10 |
install a brand new standalone system from scratch as opposed to one |
11 |
under /usr/${CHOST}. |
12 |
|
13 |
I have heard some developers say that cross-compiling is simply not |
14 |
worth the effort but I have succeeded in building some big ticket items |
15 |
including MariaDB, GTK+, Qt4, and LibreOffice. This is one area where |
16 |
Gentoo can really shine so I would like to exploit that potential. |
17 |
|
18 |
It is unlikely that I'll be able to negate the need for cross-boss |
19 |
entirely as some packages can be really stubborn but these changes |
20 |
should at least allow some of the hacks to be removed. |
21 |
|
22 |
The first change is a long-standing one and adds BDEPEND to the list of |
23 |
dependency types. For those familiar with the experimental HDEPEND |
24 |
implementation, this is the same thing under a different name that many |
25 |
developers have said they prefer. It means "build depend" for packages |
26 |
to be installed on / aka the CBUILD system. |
27 |
|
28 |
You may be thinking that is what DEPEND is for but sometimes you need |
29 |
to differentiate between build-time dependencies that are needed in / |
30 |
for execution and those that are needed in ROOT for headers, static |
31 |
libraries, and other things. |
32 |
|
33 |
This is best illustrated with an example. pam currently DEPENDs on |
34 |
flex as it links against libfl.a. By default, Portage will not install |
35 |
DEPEND packages to ROOT so this fails when cross-compiling. flex could |
36 |
be added to RDEPEND but that is suboptimal and may not be feasible in |
37 |
other cases. We could run emerge with --root-deps but this tends to |
38 |
pull in many more packages that play havoc when cross-compiling. |
39 |
|
40 |
This feature can also be particularly useful for packages like autogen |
41 |
and dbus-glib that execute themselves during the build. This doesn't |
42 |
always work when cross-compiling but you can use BDEPEND in conjunction |
43 |
with the targetroot USE flag (see man 5 ebuild) to install that package |
44 |
to / first and then use that version to complete the cross build. |
45 |
|
46 |
So when cross-compiling under EAPI 7, the traditional defaults change. |
47 |
BDEPEND is installed to / as already stated and DEPEND is now installed |
48 |
to ROOT. The --root-deps options have no effect. Won't this break |
49 |
cross-compiling for future EAPI 7 ebuilds and eclasses that haven't |
50 |
been given the BDEPEND treatment? Yes and no. crossdev's cross-emerge |
51 |
wrapper has long included the --root-deps=rdeps option by default, |
52 |
which simply throws DEPEND away and this is equally broken already. |
53 |
|
54 |
So why did crossdev include --root-deps=rdeps in the first place if it |
55 |
breaks things? The commit message doesn't really say and solar doesn't |
56 |
seem to be around to answer that question. I'm guessing it was a |
57 |
trade-off to save time. Portage currently installs all of DEPEND to / |
58 |
by default even though most of those dependencies are solely needed |
59 |
for headers and libraries. This means that when cross-compiling on a |
60 |
minimal build host, you spend almost half the time building things that |
61 |
you don't even need. This trade-off will no longer be necessary as |
62 |
BDEPEND will allow us to make that saving while avoiding the breakages |
63 |
at the same time. |
64 |
|
65 |
We do not expect all developers to be mindful of BDEPEND going |
66 |
forwards. mgorny said that this could be thought of in the same way |
67 |
that we currently don't beat developers up over mishandling of EPREFIX. |
68 |
This will mean that I or others may occasionally swoop in to apply |
69 |
BDEPEND to your packages and I hope that this isn't seen as rude or |
70 |
invasive. It should have no effect on the non-cross case and for what |
71 |
it's worth, I think I'm quite careful. :) |
72 |
|
73 |
Also on the table is a variable called BROOT, which has arisen from bug |
74 |
#509568. When calling executables from the build host, you can usually |
75 |
rely on the PATH but sometimes the binary you need isn't in the PATH. |
76 |
This obviously calls for an absolute path but what if the build host is |
77 |
prefixed? EPREFIX always refers to the target host so how can you find |
78 |
the prefix of the build host? Since the build host is always anchored |
79 |
to / and we always refer to it absolutely, a BPREFIX variable is of |
80 |
little use so we have therefore chosen BROOT. It's basically EROOT for |
81 |
the build host. |
82 |
|
83 |
Up to this point, I have referred to just the cross and non-cross cases |
84 |
for simplicity. It may really be this simple but we should explore the |
85 |
possibilities to make sure because I think one particular use case is a |
86 |
little less clear cut. |
87 |
|
88 |
-------- |
89 |
|
90 |
1. Regular native |
91 |
CHOST = CBUILD, PORTAGE_CONFIGROOT = /, ROOT = / |
92 |
|
93 |
The traditional setup we're all familiar with. Everything goes to / so |
94 |
the distinction between BDEPEND and DEPEND is irrelevant here. |
95 |
|
96 |
2. Rooted native, same config |
97 |
CHOST = CBUILD, PORTAGE_CONFIGROOT = /, ROOT != / |
98 |
|
99 |
This is almost exactly like #1 but the packages are not installed to / |
100 |
at the end. Headers and libraries are still sourced from / and as such, |
101 |
BDEPEND still doesn't apply. Despite an identical Portage configuration, |
102 |
unexpected problems can arise. I did an experiment while writing this |
103 |
and confirmed that having older libraries installed in / can lead to |
104 |
breakages. |
105 |
|
106 |
For example, say you have ncurses:0/5 installed in / and then attempt |
107 |
to install i7z in a brand new ROOT. It will install ncurses:0/6 to ROOT |
108 |
but then link the new i7z against libncurses.so.5. Furthermore, Portage |
109 |
will record it as having been built against 0/6. |
110 |
|
111 |
I think the easiest way to avoid problems like this is to ensure your |
112 |
build host is up to date before you start installing things to ROOT. |
113 |
Portage doesn't check this for you. Maybe it should? |
114 |
|
115 |
3. Cross |
116 |
CHOST != CBUILD, PORTAGE_CONFIGROOT != /, ROOT != / |
117 |
|
118 |
For all its difficulties, the theory is quite simple. You build using |
119 |
ROOT as much as possible except when you need to execute something. |
120 |
This includes headers, which must never be sourced from / as this |
121 |
quickly leads to breakages. Ensuring this happens is probably easier |
122 |
than you think. More on that later. |
123 |
|
124 |
4. Rooted native, different config |
125 |
CHOST = CBUILD, PORTAGE_CONFIGROOT != /, ROOT != / |
126 |
|
127 |
This is the messy one and one I'd like some feedback on as to what |
128 |
people expect from it and whether it should even be supported at all. |
129 |
Out of the box, it suffers from the same problems as #2 but keeping |
130 |
your build host up to date is no longer sufficient. The target's USE |
131 |
flags could potentially be entirely different, meaning that even the |
132 |
same version of the same library could differ significantly between / |
133 |
and ROOT. Even the headers could differ. |
134 |
|
135 |
As far as I can see, the only sane way to deal with this is to build |
136 |
against headers and libraries in ROOT instead, much like you would when |
137 |
cross-compiling in #3. However, this just leaves you with the same |
138 |
problem in reverse. Since you wouldn't really be cross-compiling, the |
139 |
build may attempt to execute something that was just built. This |
140 |
execution will occur in the context of the build host, which may not |
141 |
have the necessary libraries available. |
142 |
|
143 |
Perhaps you could force it to treat the build like a cross-compile by |
144 |
overriding various checks in eclasses and build systems. This does |
145 |
sound painful though. Another way would be to install an alternative |
146 |
toolchain like x86_64-cross-linux-gnu. I know of one user who |
147 |
successfully used this approach with cross-boss. It's probably not |
148 |
bullet proof though as not all build systems respect CHOST and CBUILD. |
149 |
I'm leaning towards the idea that this scenario should simply be |
150 |
unsupported. You might as well start with a stage tarball and chroot |
151 |
like usual. Do you have any better ideas? |
152 |
|
153 |
It may seem like I have drifted off the point but I mention this use |
154 |
case because we need to decide exactly when BDEPEND should apply. If |
155 |
headers and libraries are sourced from ROOT then it needs to apply, |
156 |
regardless of whether it is treated as a cross-compile or not. |
157 |
|
158 |
-------- |
159 |
|
160 |
Still with me? ;) |
161 |
|
162 |
I raised one further point with mgorny that he feels could potentially |
163 |
go into EAPI 7 but I think could remain an implementation detail. In |
164 |
cases #3 and #4 (basically when ROOT != / and PORTAGE_CONFIGROOT != /), |
165 |
the toolchain needs to know how to source headers and libraries from |
166 |
ROOT instead of /. |
167 |
|
168 |
gcc and friends support a --sysroot argument. It used to be the case |
169 |
that this didn't work on a toolchain configured without a sysroot, |
170 |
possibly creating issues for #4, but I've tested and it now works |
171 |
regardless. |
172 |
|
173 |
In cross-boss, this argument is injected through some wrappers present |
174 |
in the PATH, in a similar manner to distcc wrappers. This is remarkably |
175 |
effective but doesn't quite cover everything. |
176 |
|
177 |
CMake supports a CMAKE_SYSROOT argument that you set in the toolchain |
178 |
file. We currently don't set this but it could easily be added to |
179 |
cmake-utils.eclass as well as (or instead of?) the similar variables |
180 |
that we already do set. |
181 |
|
182 |
The vast majority of configure scripts (using libtool and not ancient) |
183 |
support a --with-sysroot argument that can easily be detected by |
184 |
grepping for lt_sysroot. The behaviour of econf is largely defined by |
185 |
PMS, hence why mgorny thinks this particular detail could go into |
186 |
EAPI 7, but it only says which arguments must be passed and doesn't say |
187 |
that the PM can't pass additional ones. I don't wish this force this |
188 |
stuff upon Paludis and pkgcore unnecessarily. |
189 |
|
190 |
There's also a further complication here that I forgot to mention to |
191 |
mgorny. While calling configure with --with-sysroot certainly helps, |
192 |
it still stumbles on a significant number of packages that do |
193 |
relinking at the end of the build if elibtoolize hasn't been called. |
194 |
elibtoolize has long patched ltmain.sh with ELT-patches/cross/link-ROOT |
195 |
when cross-compiling and this still applies to the very latest libtool. |
196 |
I filed several bugs about this before realising that fixing this |
197 |
globally would be better. elibtoolize doesn't require anything to be |
198 |
installed and the description does say "this function should always be |
199 |
safe to run" but I suppose calling it unconditionally might screw up |
200 |
patching in some isolated cases. What do you think? |
201 |
|
202 |
Phew, I'm done. Please be gentle! :) |
203 |
|
204 |
-- |
205 |
James Le Cuirot (chewi) |
206 |
Gentoo Linux Developer |