Replies: 7 comments
-
I'll read the wall of text another time. :) I'm interested in your specific use case. Wrt. Fedora, is this mainly just for the 'manual' Linux multilib package, or do you plan on building & providing more cross-compiled runtime libs directly? For the official packages, I found it quite okay to build via
This is currently done in ldc/.github/actions/merge-macos/action.yml Lines 13 to 90 in c26e843 The 2 Edit: And building, copying & .conf-extending the iOS libs in the source packages goes like this: ldc/.github/actions/5a-ios/action.yml Lines 26 to 52 in c26e843 |
Beta Was this translation helpful? Give feedback.
-
OTOH, that should be the case, more or less, with the notable jit-rt (for dynamic-compile) exception, as that requires the LLVM libs for that target. Edit: Oh, and all the compiler-rt libs are missing as well (incl.
IIRC, that trick is only employed to restrict the cross-build to the executables, excluding druntime and Phobos, which have been cross-compiled earlier (via ldc-build-runtime), so that the executables can be linked against those. The cross-compiled compiler can normally not be run on the host, so cannot build druntime and Phobos. But fully agreed, needing a list of all executables is ugly, so maybe some CMake special casing for A major hurdle for cross-compiling LDC itself is the need for target-compatible LLVM libs, coupled with a host-runnable
You mean to avoid something like |
Beta Was this translation helpful? Give feedback.
-
I guess that would lead to a massive CMake simplification, so I'm in favor of removing it soonish. |
Beta Was this translation helpful? Give feedback.
-
For the official packages, I handle this via the DFLAGS env variable, which is respected by the ldc/.github/actions/3-build-cross/action.yml Line 118 in c26e843 |
Beta Was this translation helpful? Give feedback.
-
I was planning to support cross-compiling for Gentoo packages (which users build themselves) and i did get it working to some degree but it is hacky so I want to implement it cleanly here. And if I'm going to do that I might as well cross out some other fixes/improvements.
Modifying already installed files is pretty much the only thing I can't do so that's why I insist so much on having To get a cross-gcc on Gentoo you would need to install So, based on the same logic I could install
Another reason for me doing cross-compiling in Gentoo is the addition of a way to generate a
On Gentoo specifically cross-compiling means building a package for another system, that will be installed on that system. So the package needs to contain the same files that it does when built natively. This means that I need the same dir structure, the import files, (possible) the config file so it would be easier if The only thing that I would benefit from all of these is All in all, I can get away with having some code on the Gentoo side handling these small issues and it would be OK. But it's enough code to make me want to change something upstream. Because I want that, instead of doing what is minimally sufficient for me I'm trying to get the stuff I touch in the best state that it can be. To do this I sat down and tried to figure out what would be the ideal way that this code would act, how it would be most intuitive/standard, have the least bugs, and bring the best user experience. so I can up with this. I don't know if all of these are achievable but I will try to get as close as possible. |
Beta Was this translation helpful? Give feedback.
-
Would this extra ldc2.conf file be 'installed' as part of the cross Thinking about how this could potentially work with what we currently have, without having to patch the compiler's |
Beta Was this translation helpful? Give feedback.
-
That would the plan as that would allow But, it would have consequences. Having a
|
Beta Was this translation helpful? Give feedback.
-
Cross-compiling the ldc2 runtime is a relatively painless process, either by using
ldc-build-runtime
or calling cmake in the runtime subdirectory. However, making the produced binaries usable requires manual intervention, like having to add a new section to ldc2.conf.I want to work on improving this so I want to discuss possible changes and goals to know if I should implement them or not. Feel free to propose modifications or other features you want since I don't mind working on it, I just want to know what I'm striving for.
Goals
cmake -S runtime -D...
should be enough to cross-compile the runtime, if a cross-toolchain is presentninja bin/ldc2 bin/timetrace2txt...
ninja install
should be sufficient to install a cross-compiled runtimeldc-build-runtime
may be extended to set up things that are needed for cross compiling (like downloading a cross C toolchain) but aren't part of the ldc2 project.Possible implementations
Isolate the runtime cmake from the compiler cmake more
For cross-compiling to work fully all options that affect both the runtime and the compiler should be specified twice, once in the runtime cmake and another time in the compiler cmake. This also means that the cmake files can no longer rely on options being transitively set (like the runtime assuming that llvm is present or the compiler assuming that a ldc2.conf file has been generated)
This should be able to be accomplished without too much code duplication but with slight complexity by, for example, introducing a LdcCommon module that contains all the build settings that affect both the compiler and the runtime.
Another pain point is ldc2.conf. I don't see a way that it can stay as is, there's no way to cleanly have both the compiler and runtime append their settings to it, unless it is split across multiple files. For example, a compiler could generate a wasm.conf file that contains the default switches for building for wasm and the runtime could generate x64.conf that contains switches, libdirs and rpath for building for x64. I detail this in the next section.
In terms of implementation, there should be one added cmake setting, that which controls skipping going into the runtime subproject if cmake is invoked for the compiler. Additionally some variables that affect both the compiler as well as the runtime build would need to be exposed to users (if they aren't already) so that the projects could be built independently.
The installed ldc2.conf must become a directory
There's no way for
ninja install
to install (without overwriting) config files from different builds unless the paths differ.This is a breaking change but it can be alleviated by:
Introducing a deprecation period in which users are warned that the config file will change to a directory
Supporting both a file and a directory config, but cross-compiling will only work (without intervention) if the user has a directory config.
The first option is the lazy one, with minimal code footprint. The second require a little bit more code but the
ldc-build-runtime
could be used to install the config file, by concatenating the build generated file to theldc2.conf
present on the user system.This choice is solely for how
ldc2.conf
is installed, the compiler would still support loading both a file or a directory config, if the user points it to it.I prefer the second option since it doesn't really have a downside is pretty minimal but the UX is better.
On the details of implementation it would require two cmake variables (names may be changed)
LDC_CONFIG_PREFER_DIR
- install the config files as a directory instead of as a file (default disabled for backwards compatibility)LDC_DONT_INSTALL_CONFIG
- skip installing the config file.This is probably the easiest way to avoid overwriting a ldc2.conf file installed on a user system.
ldc-build-runtime
would set this variable and pick up the config file from the build directory in this case.Make the section name in the runtime
ldc2.conf
configurable.There are two reasons for this:
default
would be broken-DMULTILIB=ON
) may be unwanted since the cross-compiled objects may be used for more targets compared to the target triple (or the same target may have more spellings likeaarch64-windows
andarm64-windows
).This would add yet another cmake option. The default value for this setting can stay the target triple (without the vendor, like
x86_64-.*-linux-gnu
). This is the same wayMULTILIB
handles it.Support for target-dependent headers
This is more of a future-proof thing, but imagine you want to target some linux system and use functions provided by glibc. If you are targeting glibc-2.28 it is expected that you won't have the same functions available as on glibc-2.40. Of course,
core.sys.linux.*
doens't currently have that capability but I think that having support for this will pay off in the future.The implementation would be simple. The runtime would install two config files:
runtime-common.conf
runtime-lib<suffix>.conf
Then, the same build would install platform-independent headers (like phobos, most of druntime) into
include/d
and the rest of the headers into whichever directory it deems appropriate (one example could beinclude-lib<suffix>
).Since there are currently no platform-specific headers there's no reason to consider which target specific switch would be present or where to install the headers. The only relevant thing is having the split between the two config files.
When another runtime would be built and installed it would overwrite the
runtime-common.conf
file, but since it contains the same include path there would be no issue, as well as overwriting all ofinclude/d
but, again, the files would stay the same so it will be all right.Remove (or deprecate) MULTILIB
If cross-compiling becomes usable out-of-the-box
-DMULTILIB=ON
could be replaced by callingldc-build-runtime --dFlags=-m32
. Additionally, since cmake doesn't support looking for packages for multiple architectures in the same build, the-DMULTILIB=ON
setting would prevent the x86 build from either finding zlib or llvm, whereasldc-build-runtime
would be able to find them.-DMULTILIB
also affects the compiler by running the dmd testsuite for -m32 as well. In order to avoid losing this feature a cmake option could be introduced which will contain a list of triple-like flags to be tested.Standard way of specifying the triple
Since the main topic is cross-compiling the runtime, a very important thing is being able to specify the target system. Currently this is supported by using
D_FLAGS
for the runtime andD_COMPILER_FLAGS
for the compiler. This is different from the norm as those types of settings are usually for flags that aren't vital for the build (like-O
and-g
). The standard way of specifying the cross-compiler is by putting its flags into the compiler variable. Cmake does this by having-DCMAKE_C_COMPILER
be set to a list of two elements, firstly the compiler path followed by a space-separated list of arguments. For example-CMAKE_C_COMPILER='D:/llvm 19/bin/clang;-target i686-pc-linux-gnu'
.In ldc2,
D_COMPILER
can be used in a similar way, albeit it always splits by (unqouted) spaces. So-DD_COMPILER='"C:/ldc 1.40/bin/ldc2" -mtriple i686-pc-linux-gnu'
would be the equivalent. UnfortunatelyLDC_EXE_FULL
doesn't have such capabilities and the only way to pass the triple is throughD_FLAGS
.For the sake of standardisation I propose (again) that
LDC_EXE_FULL
either follow theCMAKE_C_COMPILER
orD_COMPILER
format. Having it followCMAKE_C_COMPILER
is slightly preferred since that won't require users to add quotes if their full path contained spaces before.ldc-build-runtime
being able to setup a cross-C or other toolchainsThis is pretty low on my list of priorities but I will try to get to it after the other issues are solved so I don't have many comments (nor do I currently have the knowledge on how non-Gentoo systems handle their cross-toolchains).
Beta Was this translation helpful? Give feedback.
All reactions