Open nurupo opened 6 years ago
You don't need to cross-compile appimagetool. You just need the right runtime for your platform. You can e.g., download the i386 runtime, and use it with appimagetool by passing via a CLI parameter.
download the i386 runtime
Oh, I forgot to mention that I want to build AppImage from source, without downloading pre-built executables.
I'm just trying to say that it should suffice cross-compile the runtime. That could save a lot of time.
That's great to know. How do I cross-compile just the runtime?
Well, you could just call make runtime
, couldn't you? You'd still need to compile the dependencies, though.
Actually, I have plans to extract the runtime from the AppImageKit project, and move it into a separate repo. That'd make building it easier.
Also, is the runtime enough for linuxdeployqt? Because I also use linuxdeployqt to -bundle-non-qt-libs -appimage
my Qt program.
linuxdeployqt bundles appimagetool, and it is hardcoded how appimagetool is called from it. Better don't use -appimage
but download and call appimagetool directly with the correct options.
Better don't use -appimage but download and call appimagetool directly with the correct options.
What do you mean by this?
@probonopd please read the rest of the thread, and you'll see what is meant by that. There is no way to tell linuxdeployqt to tell appimagetool use a custom runtime with -appimage
.
Ah right, to use advanced options of linuxdeployqt one needs to run it manually, not using the -appimage
option of linuxdeployqt
. This is intentional so that only people who know what they are doing get exposed to the linuxdeployqt
command line options.
Ah right, to use advanced options of linuxdeployqt one needs to run it manually, not using the -appimage option of linuxdeployqt. This is intentional so that only people who know what they are doing get exposed to the linuxdeployqt command line options.
JFYI linuxdeploy's AppImage plugin aims to provide more configurability how the AppImage is generated.
@nurupo I will try to rewrite the runtime build script in CMake today, that'll help making AppImageKit more cross compile friendly.
Perhaps we can even get rid of the 32-bit version of your AppImageBuild containers, build a multilib version of gcc and build the 32-bit versions of the dependencies in there as well. Then, the 32-bit builds could be created through cross compiling in the 64-bit container, using a toolchain like https://github.com/TheAssassin/linuxdeploy/blob/master/cmake/toolchains/i386-linux-gnu.cmake.
Perhaps we can even get rid of the 32-bit version of your AppImageBuild containers
Um, those are not my containers at https://github.com/AppImage/AppImageBuild. My container is provided in the opening post of this thread and it does use multilib gcc to build 32-bit versions of my software and the AppImage on a 64-bit machine, notice the -m32
in my toolchain wrapper scripts, and it does use a CMake toolchain file to make CMake use those wrappers. Also, Debian's gcc has multilib support, there is no need to build gcc from source, just install gcc-multilib
and g++-multilib
packages.
@nurupo the point is that we can make use of cross compilation support ourselves, and that increases the priority of this issue, which is in your interest.
I know you don't use AppImageBuild, but we do. And if you look into the Dockerfiles, you'll see that we don't use Debian, we use a really old version of CentOS. We're building our own compiler because it won't work with the outdated one the CentOS packages allow us to use. Same goes for a couple of other dependencies, e.g., GLib.
Here is a bit more advanced script I use to build for amd64, arm64, armel, armhf, i386, mips, mips64el, mipsel, ppc64el and s390x architectures. It doesn't build successfully for all of them, qemu-user-static
bugs out on some architectures, preventing things to be built. Don't remember for which exactly it bugs out, but it works just great for amd64, arm64, armel, armhf and i386. Note that the script is without a license for now. I'm planning on adding it later once I'm done doing what I'm doing, but if you want to use it now I could add it now.
@nurupo thanks for the share, I'll check it out, but as I said the scripts are going to be "converted" to CMake code, which makes the whole build a bit more consistent and less complex. Then, a toolchain like I shared above should allow for cross-compiling everything without any major hassle.
There is no need to convert those bash scripts to CMake code. Ideally you should just set the c compiler, linker, emulator and such in the toolchain file and it should just work with any toolchain, even android, for example.
As far as the AppImageKit goes, src/build-runtime.sh.in
should use c compiler, linker, objcopy, readelf, etc. found by CMake (potentially from a toolchain file), e.g. CMAKE_C_COMPILER
and such variables, instead of hardcoding gcc
, ld
and so on. It should also pass those c compiler and other CMake variables to any AppImageKit dependency the CMake compiles, e.g. mksquashfs, because just calling ./configure won't use the cross-compilation toolchain and will pick up the system gcc. It also needs to use CMAKE_CROSSCOMPILING_EMULATOR
variable and CROSSCOMPILING_EMULATOR
target property, which could be either empty or set to qemu by the user through a toolchain file when crosscompiling, to run programs that might potentially be of other architecture.
As far as LinuxDeployQt goes, I don't even know where to start. It hardcodes a lot of things and there is also this whole ldd issue. I made it work by overwriting the hardcoded programs it calls with scripts that call the programs I want it to use instead, but that's just a hack, it really needs a way to specify which programs to use instead of hardcoding their names. I believe you are also working on its replacement, so let's just not discuss LinuxDeployQt.
I tried to pass the right parameters to these build systems, but it didn't really work very well. Therefore I'd rather build the libraries using some custom CMake code in the future.
Regarding the ldd
issue, linuxdeploy uses ldd
, too, but only until we get to writing our own replacement (i.e., parse the ELF header field and implement our own search algorithm that works like ldd
). See https://github.com/TheAssassin/linuxdeploy/blob/master/src/core/elf.cpp#L69. If you want to give it a try now, we can e.g., introduce an environment variable $LDD
or something like that which can be used to override the path to the ldd
that shall be used. Please feel free to try out linuxdeploy and open issues improving cross compiling support, your comments are highly appreciated.
I see #818 still uses hardcoded objcopy
. How about having a OBJCOPY_COMMAND
variable which user can set, e.g. through a toolchain file, and if it's not set then it defaults to objcopy
, and you actually check if the user-specified command or objcopy
exist with find_program()
?
Something like this
if (NOT OBJCOPY_COMMAND)
set(OBJCOPY_COMMAND objcopy)
endif()
find_program(OBJCOPY_COMMAND_FOUND ${OBJCOPY_COMMAND})
if (NOT OBJCOPY_COMMAND_FOUND)
message(FATAL_ERROR "Couldn't find \"${OBJCOPY_COMMAND}\" program. Make sure you have it installed. You can also specify path to it in OBJCOPY_COMMAND variable if it's still not being found.)
endif()
set(OBJCOPY_COMMAND ${OBJCOPY_COMMAND_FOUND})
# Now use ${OBJCOPY_COMMAND} in the commands
If user does
set(OBJCOPY_COMMAND /foo/bar/whatever-linux-gnu-objcopy)
in a toolchain file, then /foo/bar/whatever-linux-gnu-objcopy
will be used. If the user doesn't set it, then objcopy
will be used. CMake will try to confirm that both /foo/bar/whatever-linux-gnu-objcopy
and objcopy
programs actually exist.
Any other programs which must be configurable?
All of those. That's as of a01f60bb728af07a73644e677d73467985e8dca7 though, not sure if they are still used.
Added a TOOLS_PREFIX
in https://github.com/AppImage/AppImageKit/commit/f8697f5c84a885cc44f70a79e40fdb8cfa86c92f that you can set to make the search for programs prefer tools with that prefix, and use the non-prefixed version if there's none with the prefix. The paths are logged during configuration, making the whole process transparent to the user.
I will replace calls to the tools you listed here to use the programs found with check_program
instead.
Then, that part should be fixed.
Regarding cross-compilation support, I'm making progress with the dependencies (our CMake infrastructure always supported cross-compilation). I'll push that stuff soon.
https://github.com/AppImage/AppImageKit/tree/cross-compiling provides a way to cross compile AppImageKit from x86_64 to i386.
To test it, I'll try to cross-compile libappimage for AppImageLauncher using the provided toolchain file.
32-bit cross compiling works fine now.
Hm, now that I revisit my build script, I notice that I used qemu only for LinuxDeployQt, I don't use it for AppImageKit, so AppImageKit probably has no need to run foreign architecture programs, meaning that my suggestion of making AppImageKit use CMAKE_CROSSCOMPILING_EMULATOR
is probably a pointless one.
32-bit cross compiling works fine now.
What about armel?
I did not try. But I didn't actually intend to close this issue (been a long week), I'll reopen this.
If you have concrete suggestions how we can improve cross-compiling support, please let me know.
I want to cross-compile my program to several architectures (e.g. i386, x86_64, armel, armhf, etc.) and publish each as an AppImage. Besides cross-compiling my own application, I found that AppImageKit itself needs to be cross-compiled for each architecture in order to create the AppImage bundles for them. However, it has proven to be rather challenging to cross-compile AppImageKit.
src/build-runtime.sh.in
andcmake/dependencies.cmake
are the biggest cross-compilation offenders here.src/build-runtime.sh.in
assumes that the build is made using system's native toolchain, it usesgcc
,strip
,readelf
,ld
, etc. without any way to specify the triplet prefix.cmake/dependencies.cmake
builds dependencies not found on the system without ability to set--host=
configure's argument, which results in the build failure when cross-compiling.Here are full examples of how I have patched AppImageKit when cross-compiling it to armel and i386 on an x86_64 machine, so that you could see what I'm talking about and be able to reproduce:
armel
i386