Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 503216 - cmake-utils.eclass - fix cross-compile support
Summary: cmake-utils.eclass - fix cross-compile support
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Eclasses (show other bugs)
Hardware: All Linux
: Normal normal with 1 vote (vote)
Assignee: Gentoo KDE team
URL:
Whiteboard:
Keywords: PATCH
Depends on:
Blocks: 503218
  Show dependency tree
 
Reported: 2014-03-02 16:07 UTC by James Le Cuirot
Modified: 2014-11-01 08:09 UTC (History)
3 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments
cross-cmake-eclass.patch (cross-cmake-eclass.patch,1.60 KB, patch)
2014-03-02 16:07 UTC, James Le Cuirot
Details | Diff
smaller patch (cmake-utils.patch,704 bytes, patch)
2014-10-13 09:15 UTC, Alexis Ballier
Details | Diff
patch (cmake-utils.patch,2.54 KB, patch)
2014-10-14 09:05 UTC, Alexis Ballier
Details | Diff
cmake-utils-x-compile.patch (cmake-utils-x-compile.patch,3.21 KB, patch)
2014-10-24 14:48 UTC, Alexis Ballier
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description James Le Cuirot gentoo-dev 2014-03-02 16:07:18 UTC
Created attachment 371566 [details, diff]
cross-cmake-eclass.patch

I thought that CMake on Gentoo already handled cross-compiling properly. Maybe something changed or maybe I was just lucky in the past. I now find that it is not adding -fPIC when appropriate because it is not properly detecting GCC and it is also not generally aware that it is actually cross-compiling. The documented way to cross-compile is to provide a toolchain file. At the very least, you need to provide a C compiler, C++ compiler, and system name as returned by uname -s. Obviously we can't run the target's uname but in most cases, Portage's KERNEL variable is a good match and the rest can be fixed up. /usr/share/cmake/Modules/CMakeDetermineSystem.cmake is a useful reference. The attached patch has worked for any CMake-based packages I have tried so far.

I have also fixed the CMake ebuild itself so that it cross-compiles but I will file a separate bug report for that.
Comment 1 Luke-Jr 2014-04-22 18:20:31 UTC
Patch doesn't seem to work for me... For a x86_64-w64-mingw32 target, I end up with:
  SET (CMAKE_SYSTEM_NAME "Linux")
  SET (CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc)
  SET (CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++)
Comment 2 James Le Cuirot gentoo-dev 2014-04-22 19:20:15 UTC
An appropriate Portage profile needs to be set. Do this by repointing the /usr/x86_64-w64-mingw32/etc/make.profile symlink to somewhere under /usr/portage/profiles/prefix/windows. crossdev points this to /usr/portage/profiles/embedded by default for all targets but this should generally be changed.
Comment 3 Luke-Jr 2014-04-22 20:10:06 UTC
(In reply to James Le Cuirot from comment #2)
> An appropriate Portage profile needs to be set. Do this by repointing the
> /usr/x86_64-w64-mingw32/etc/make.profile symlink to somewhere under
> /usr/portage/profiles/prefix/windows. crossdev points this to
> /usr/portage/profiles/embedded by default for all targets but this should
> generally be changed.

I don't see any 64-bit profiles...
Comment 4 James Le Cuirot gentoo-dev 2014-04-22 20:38:19 UTC
Heh okay but we're drifting outside the scope of this report slightly. There are profiles specific to "x86" under there but you could probably get away with choosing one of the parent directories, which don't specify any arch. The embedded profile you were using before doesn't specify any arch either.

This begs the question as to what you've set ACCEPT_KEYWORDS to. crossdev defaults to "unknown ~unknown" for mingw32, which won't get you very far. "x86-winnt" is supported but even that is only present on a handful of packages. No 64-bit equivalent is supported.

You wouldn't be the first to try and use Portage to build software with the x86_64-w64-mingw32 toolchain as I've done it a little myself but you're a little off the beaten track in terms of what is actually supported. ;)
Comment 5 Luke-Jr 2014-04-22 20:48:08 UTC
(In reply to James Le Cuirot from comment #4)
> This begs the question as to what you've set ACCEPT_KEYWORDS to. crossdev
> defaults to "unknown ~unknown" for mingw32, which won't get you very far.
> "x86-winnt" is supported but even that is only present on a handful of
> packages. No 64-bit equivalent is supported.

crossdev gave me:
ACCEPT_KEYWORDS="amd64 ~amd64"

> You wouldn't be the first to try and use Portage to build software with the
> x86_64-w64-mingw32 toolchain as I've done it a little myself but you're a
> little off the beaten track in terms of what is actually supported. ;)

Well, this works for just about everything else (with the embedded profile)... I've been using it for years now.
Comment 6 James Le Cuirot gentoo-dev 2014-04-22 21:15:14 UTC
Fair enough. I thought about suggesting "amd64" but wasn't sure if that was such a good idea. Evidently it works for you. I would stick with that and try a profile of just /usr/portage/profiles/prefix/windows/winnt. Failing that, try simply setting KERNEL="Winnt" in your make.conf.
Comment 7 James Le Cuirot gentoo-dev 2014-04-27 20:15:58 UTC
Any joy, Luke?

Just to let you know that I've now managed to build MariaDB and MySQL using this patch but it also requires a small addition to mysql-cmake.eclass as well as a few changes to the the build scripts. I've submitted a patch upstream to MariaDB so I'll wait to see what happens there before filing another bug report here.
Comment 8 Luke-Jr 2014-04-27 20:50:12 UTC
Seems to work in general, but not for libwebsockets which I was trying to make an ebuild for (it fails to find ZLIB) :(
Comment 9 James Le Cuirot gentoo-dev 2014-04-27 22:59:44 UTC
That is probably a different issue as I don't believe the toolchain file does anything to help with properly locating headers and libraries. Autotools-based software frequently suffers from these kinds of problems and I have tried to tackle these and more in my cross-boss project. I would point you to it but I don't think it'll help for Windows targets.
Comment 10 Alexis Ballier gentoo-dev 2014-10-13 09:15:58 UTC
Created attachment 386594 [details, diff]
smaller patch

Hi James,

your patch didn't seem to help with cmake-3.0.2 here. This smaller patch fixes the compiler id issue here. Could you please test it?

@kde: mind if I apply it ?
Comment 11 Tomáš Chvátal (RETIRED) gentoo-dev 2014-10-13 09:26:53 UTC
Knock yourself out and commit it.
Comment 12 James Le Cuirot gentoo-dev 2014-10-13 12:30:30 UTC
Alexis, is there a specific package you are having trouble with? I just updated CMake to 3.0.2 and managed to cross-compile OpenAL, Yajl, and even CMake itself (see bug #503218) using my fix. I also tried without to make sure it was really still needed; it still fails in the same manner. What I have proposed is the documented method for cross-compiling so I wonder if the package you're having trouble with is unusual in some way.
Comment 13 Alexis Ballier gentoo-dev 2014-10-13 12:56:08 UTC
(In reply to James Le Cuirot from comment #12)

well, maybe I did something wrong; openal is fine with the tc-export too.

what I don't like with your patch is that it seems a bit duplicate with the gentoo_rules.cmake; if CMAKE_TOOLCHAIN_FILE is the way to go then maybe cmake-utils.eclass should always define its toolchain here, cross compiling or not.
Comment 14 James Le Cuirot gentoo-dev 2014-10-13 14:19:50 UTC
Interesting. I didn't try the tc-export method until just now but it does indeed work here too. In the comment, you say that without the fix it simply uses "gcc" but that's not what I'm seeing. With no fix at all, it is definitely using armv7a-hardfloat-linux-gnueabi-gcc here but I do see this:

-- The C compiler identification is unknown

Later followed by this error:

/usr/libexec/gcc/armv7a-hardfloat-linux-gnueabi/ld: CMakeFiles/yajl.dir/yajl.c.o: relocation R_ARM_MOVW_ABS_NC against `a local symbol' can not be used when making a shared object; recompile with -fPIC

Given that it's already using the correct gcc, it seems strange that simply exporting CC should make a difference. I'm all for a simpler fix of course but I'm not confident that this would work properly when targeting a different OS such as Linux -> Windows. It needs to know the OS so that it can name libraries correctly, i.e. .so vs .dll.

Using a toolchain file all the time doesn't sound like a bad idea. The CMAKE_CROSSCOMPILING variable is only set to true when CMAKE_SYSTEM_NAME is set so we could leave this out, although I seem to recall that CMAKE_SYSTEM_NAME is actually required so this might not work.
Comment 15 James Le Cuirot gentoo-dev 2014-10-13 14:36:47 UTC
Just tried leaving out CMAKE_SYSTEM_NAME, seems to work. Also tried removing the CC/CXX stuff from gentoo_rules.cmake and that worked too. I was wondering what to do about the other tools. This thread says that setting CMAKE_AR and CMAKE_RANLIB in the toolchain file can be problematic but CMakeFindBinutils.cmake should find them with the help of the other variables. This was a while ago though and it may have been fixed since.

http://www.cmake.org/pipermail/cmake/2010-March/035540.html
Comment 16 Alexis Ballier gentoo-dev 2014-10-13 14:38:22 UTC
(In reply to James Le Cuirot from comment #14)
> Interesting. I didn't try the tc-export method until just now but it does
> indeed work here too. In the comment, you say that without the fix it simply
> uses "gcc" but that's not what I'm seeing. With no fix at all, it is
> definitely using armv7a-hardfloat-linux-gnueabi-gcc here but I do see this:
> 
> -- The C compiler identification is unknown

yes, and if you look at the error log you see it uses plain gcc for this guess

[...]
> I'm all for a simpler fix of course
> but I'm not confident that this would work properly when targeting a
> different OS such as Linux -> Windows. It needs to know the OS so that it
> can name libraries correctly, i.e. .so vs .dll.

it would probably not work indeed (that's not what I am doing :) ) but I left that out because I'm not sure if the KERNEL variable is supposed to be available to ebuilds, CHOST might be better but I'm not sure
Comment 17 James Le Cuirot gentoo-dev 2014-10-13 15:01:09 UTC
(In reply to Alexis Ballier from comment #16)
> yes, and if you look at the error log you see it uses plain gcc for this
> guess

Aaah, now it makes sense! I probably observed the same thing when I initially worked on this but the details were forgotten.

> it would probably not work indeed (that's not what I am doing :) ) but I
> left that out because I'm not sure if the KERNEL variable is supposed to be
> available to ebuilds, CHOST might be better but I'm not sure

Damn those pesky specifications! ;) Seriously though, aren't variables set in the profile generally considered to be available? The man pages don't mention KERNEL except in this one part of man portage.

USE_EXPAND_VALUES_KERNEL = [space delimited list of KERNEL values]
Defines KERNEL values used to generate implicit IUSE for ebuilds using EAPI 5 or later.

I think it's safe to use and if it's only set when cross-compiling, which is currently broken anyway, then this can only help matters.
Comment 18 Alexis Ballier gentoo-dev 2014-10-14 09:05:47 UTC
Created attachment 386664 [details, diff]
patch

okey, so here is a new patch proposal with your changes integrated

I added sysroot support for crossdev's emerge wrappers otherwise I get hunders of warnings that -I/usr/include/... poisons include path when cross-compiling and sometimes it even breaks.

I changed a bit the logic of your KERNEL variable handling: default now sets sysname=Linux so in case it is undefined it would not break the majority of our use-cases

I had to drop the 'type -P' in front of tc-getC{C,XX} because it breaks multilib builds where CC is set to something like "gcc -m32"


all my tests were successful, with cmake-3.0.2 and stable (2.8.12.2-r1): standard builds, multilib builds, crossdev wrappers cross compilations.
Comment 19 James Le Cuirot gentoo-dev 2014-10-14 09:59:52 UTC
I like it but this logic around KERNEL would be better.

	case "${KERNEL:-linux}" in
		Cygwin) sysname="CYGWIN_NT-5.1" ;;
		HPUX) sysname="HP-UX" ;;
		linux) sysname="Linux" ;;
		Winnt) sysname="Windows" ;;
		*) sysname="${KERNEL}" ;;
	esac

The reason being that, as I stated in my initial post, the other possible values for KERNEL already match what CMake expects. FreeBSD is a good example. Now it'll only fall back to Linux if KERNEL is really empty.

I didn't know about the sysroot feature. That's great because while I've been able to fix up libtool-based packages by feeding in --sysroot (see my cross-boss project), I've had to rely on gcc wrappers for other packages. I'll still need those but at least CMake will handle things properly now.

I'll test this as soon as I can.
Comment 20 Alexis Ballier gentoo-dev 2014-10-14 10:15:28 UTC
(In reply to James Le Cuirot from comment #19)
> The reason being that, as I stated in my initial post, the other possible
> values for KERNEL already match what CMake expects. FreeBSD is a good
> example. Now it'll only fall back to Linux if KERNEL is really empty.

right, missed that point, fixed locally, thanks
Comment 21 James Le Cuirot gentoo-dev 2014-10-14 19:03:10 UTC
Now tested with the aforementioned packages. Looks good.
Comment 22 Alexis Ballier gentoo-dev 2014-10-24 14:48:26 UTC
Created attachment 387312 [details, diff]
cmake-utils-x-compile.patch

Ok, so here is another round, after some more testing locally; hopefuly the last one:

- I removed the 'set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)'; cmake will default to BOTH which makes more sense and will prefer sysroot files if present.
- I added CMAKE_EXTRA_CACHE_FILE variable which is needed to feed cmake with TRY_RUN results; I don't think we can have something as simple as config.site for cmake so these files should be fed by user: This should help you for cross-compiling cmake itself.


@kde team: any objection I commit this?
Comment 23 Michael Palimaka (kensington) gentoo-dev 2014-10-25 14:25:41 UTC
(In reply to Alexis Ballier from comment #22)
> @kde team: any objection I commit this?

No worries, thanks for solving the issue.
Comment 24 Alexis Ballier gentoo-dev 2014-10-27 09:49:21 UTC
(In reply to Michael Palimaka (kensington) from comment #23)
> (In reply to Alexis Ballier from comment #22)
> > @kde team: any objection I commit this?
> 
> No worries, thanks for solving the issue.

applied then, closing
Comment 25 Maxim Britov 2014-10-31 16:08:29 UTC
freerdp can't build with cmake-utils.eclass revision=1.112, 1.111 builds fine.

With 1.112 it fails:
CMake Error at winpr/CMakeLists.txt:20 (project):
  The CMAKE_C_COMPILER:

    x86_64-pc-linux-gnu-gcc

  is not a full path and was not found in the PATH.
Comment 26 Michael Palimaka (kensington) gentoo-dev 2014-10-31 16:10:39 UTC
(In reply to Maxim Britov from comment #25)
> freerdp can't build with cmake-utils.eclass revision=1.112, 1.111 builds
> fine.
> 
> With 1.112 it fails:
> CMake Error at winpr/CMakeLists.txt:20 (project):
>   The CMAKE_C_COMPILER:
> 
>     x86_64-pc-linux-gnu-gcc
> 
>   is not a full path and was not found in the PATH.

Please file a new report about this.
Comment 27 James Le Cuirot gentoo-dev 2014-10-31 20:43:37 UTC
Maxim has not created another bug report yet but I feel this is important so I will comment here. Despite what the error says, I have seen more than one comment stating that CMake 3 now requires an absolute path. That might have something to do with why the "type -P" stuff was there. I'm not sure why this error doesn't appear on every package though. Alexis, over to you.
Comment 28 Maxim Britov 2014-11-01 08:09:25 UTC
https://bugs.gentoo.org/show_bug.cgi?id=527700