- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 270
Add LDC_TARGET_PRESET CMake variable for runtime, to make cross-compilation easier #2301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
669b19d    to
    5e46600      
    Compare
  
    | Updated this pull to keep  @kinke, what do you think?   | 
| I think it's great for convenience and may get more people to try it out if they aren't confronted with your existing huge command line. ;) I don't know any details about Android/ARM, so I don't know whether assuming ARMv7a and $NDK/toolchains/arm-linux-androideabi-4.9 is generic enough to work in most cases. And I don't know if the Android NDK for non-Linux hosts are compatible enough, so that it works on most hosts. For Windows/MSVC targets, I guess it won't be that easy; I haven't heard of a full C++ cross-toolchain yet, so while clang and lld are most likely required (and available) on non-Windows hosts, I doubt the MS libraries are easily available. For Linux x86(_64) targets, clang is probably a good choice as common C compiler, but I guess linker and libraries may be incompatible across distros/versions, and the linker may not be available on other hosts such as Windows (unless lld can really be used to target common Linux distros). But then the linker is only required for the shared runtime libs and testrunners, so being at least able to build the static runtime libs may suffice in many cases. In the future, the C libraries could be fetched from the distro's package repos (templates for Ubuntu x.y, Fedora x.y, Arch x.y...). As to OSX, I have absolutely no idea/experience at all. | 
| Wrt. linker, I forgot that we use the CMake archiver for the static runtime libs. We should probably use LDC instead, as it handles (cross-)archiving internally via LLVM. | 
| (+1 for not using the default CMake archiver for static runtime libs. Generating LTO runtime libs is currently painful because of it; you have to override CMAKE_AR and CMAKE_RANLIB because the default tools most likely do not understand object files with LLVM IR in it) | 
| Thanks Johan => #2309 so that we don't forget. | 
| 
 The NDK build script compiles for all Android-supported architectures by default, including x86, ARMv7, and ARMv5, but I see that they're deprecating the ARMv5 build in the upcoming r16 release, currently in beta. As for the gcc-toolchain, it's the only one they provide, so it will have to work. If you mean the version number, they very occasionally bump it, no big deal to match that. As for the Mac/Windows NDKs, haven't tried them, but doubt they're too different. 
 Why would you need a "full C++ cross-toolchain?" We're just building a handful of C/ASM files for the D stdlib, just like any other platform. As for the MS C libraries, yeah, up to them to deal with that. We can only do so much. As for Mac/linux, yeah, we can help them easily generate the stdlib static libraries, but after that it's up to them to supply C libraries, though we can make their life easier with your lld pull #2203. | 
| 
 [I was already thinking about the full cross-compilation package incl. target C libs for full cross-linking support. C++ because I was already thinking about being able to cross-compile LDC itself. ;)] | 
| btw, I cross-compiled the ldc compiler itself for Android/ARM with the NDK for the first time when I wrote up the Termux build script a couple months ago, termux/termux-packages#1078, as I was only compiling the native compiler on my Android/ARM tablet before that. I haven't had a problem, so cross-compiling ldc itself at least works for Android/ARM, that too the ddmd 1.3 and 1.4 beta versions which require building a bootstrap ldc cross-compiler first. | 
| 
 Almost certainly only because you've cross-compiled from Linux to Android-Linux. LDC's CMake script still needs to be prepared for general cross-compilability. | 
| Yeah, but is there much left? I'll try it on wine with the Android NDK for Windows and let you know how it goes. | 
| There are at least multiple  Another likely problem is that we're invoking the  | 
| Renamed  Update: Oh, I wonder if it'd be worth adding the cross-compilation target triple and its settings to ldc2.conf automatically too? | 
        
          
                runtime/CMakeLists.txt
              
                Outdated
          
        
      |  | ||
| cmake_minimum_required(VERSION 2.8.9) | ||
|  | ||
| set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}) | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't love this, but the alternative was to stick the new CMake module in ../cmake/Modules and add that path here, so this config could be invoked on its own by ldc-build-runtime, but I believe that would make the top-level config look outside the ldc source directory, so figured this was better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's also CMAKE_CURRENT_SOURCE_DIR which should be able to get rid of the top-level CMakeLists.txt patch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, will look into that.
1b6bfb9    to
    f97d7cc      
    Compare
  
    acb02f2    to
    04af3dd      
    Compare
  
    | Man, getting this running under Windows is a pain, as linux/x64->Android/ARM cross-compilation could use tools like the system  | 
| #2319 hopefully works for cross-compilation scenarios too (requiring an  | 
| Alright, finally seems to be working well with this latest commit, running  The last two flags were necessary to get cross-compiing to work.  If I don't change the  Ideally, the last two shouldn't be necessary, but that's the minimum I had to do to wrestle CMake down.  I'll add those to  | 
| Nice. #2319 would/should render setting ar and ranlib obsolete. | 
| @@ -1,7 +1,9 @@ | |||
| project(runtime) | |||
| project(runtime C) | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default is C and CXX, but since we don't use C++ in the runtime, took it out.  Otherwise, CMake insists on a C++ compiler and then runs some tests that break.
| Updated this pull to add flags for  Just need to push these new flags into  | 
        
          
                runtime/CMakeLists.txt
              
                Outdated
          
        
      | set(C_SYSTEM_LIBS AUTO CACHE STRING "C system libraries for linking shared libraries and test runners, separated by ';'") | ||
| set(TARGET_SYSTEM AUTO CACHE STRING "Targeted platform for cross-compilation (e.g., 'Linux;UNIX', 'Darwin;APPLE;UNIX', 'Windows;MSVC')") | ||
| set(TARGET_SYSTEM AUTO CACHE STRING "Target OS/toolchain for cross-compilation (e.g., 'Linux;UNIX', 'Darwin;APPLE;UNIX', 'Windows;MSVC')") | ||
| set(PRESET_TARGET AUTO CACHE STRING "Use preset target configuration for cross-compilation, by passing format OS-arch (e.g., 'Linux-arm', 'Mac-x64', 'Windows-aarch64', 'Android-x86')") | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defaulting to an empty string makes more sense to me, as it isn't auto-detected later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
        
          
                runtime/CMakeLists.txt
              
                Outdated
          
        
      | endif() | ||
| endif() | ||
|  | ||
| include(PresetRuntimeConfiguration) | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to line 50, so that the TARGET_SYSTEM condition doesn't change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They're mutually exclusive, see the first check in the included module, shouldn't matter.  There is a possibility that someone might manually set both TARGET_SYSTEM and PRESET_TARGET to inconsistent systems, but this order won't affect that.
Or do you mean that TARGET_SYSTEM will be set by the included module before the above block?  If so, it won't change anything either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you mean that TARGET_SYSTEM will be set by the included module before the above block?
Exactly, it is currently overwritten after bogus autodetection if a supported preset is used. So evaluating PRESET_TARGET before TARGET_SYSTEM autodetection makes more logical sense to me, and the existing condition for TARGET_SYSTEM-autodetection doesn't need to change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't be overwritten, because the included module will always set TARGET_SYSTEM to something other than AUTO if PRESET_TARGET is set. If PRESET_TARGET is AUTO, the included CMake module does nothing.  I fail to see a situation where both the above TARGET_SYSTEM auto-detection block and the new presets CMake module will be run, so the order won't matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sry got that mixed up, there's the additional condition in the autodetection block (which bothers me) which prevents the overwrite. What I mean is that it makes just more sense to evaluate PRESET_TARGET first, to fully decouple the TARGET_SYSTEM autodetection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see, run the module first, then I don't need to check for PRESET_TARGET in the auto-detection block, because TARGET_SYSTEM will be set. Makes sense, I only did it this way because I initially figured auto-detection should commonly take precedence, but I will reorder and remove the check, as you say.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. It would also fix a bug: if PRESET_TARGET is an unsupported preset, currently it doesn't do anything (a warning wouldn't hurt I guess). So skipping the autodetection for PRESET_TARGET != AUTO leaves TARGET_SYSTEM at AUTO.
        
          
                runtime/ldc-build-runtime.d.in
              
                Outdated
          
        
      | " * CMake\n" ~ | ||
| " * either Make or Ninja (recommended, enable with '--ninja')\n" ~ | ||
| " * C toolchain (compiler and linker)\n" ~ | ||
| "--presetTarget currently supports Android-arm or Android-aarch64.\n" ~ | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer having this in the --presetTarget help text.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about adding a --listPresets flag, but considering it's basically just one that works right now, figured this is enough.  Do we have time to add more preset configurations before the release, such as linux/PPC or linux/armhf, or do you still want to get it out this weekend?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going on vacation, so I'd rather release pretty soon. LDC 1.5 isn't far, so I don't mind postponing a few non-crucial things. Not sure about the weekend though, the _d_dso_register stuff is making me feel somewhat at unease.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added an example for the flag above.
| Other projects have been moving towards prefixing all their CMake variables, e.g.  | 
1042b7e    to
    75859f6      
    Compare
  
    | Made all the changes asked for, just going to see what can be done with ldc2.conf and will remove the WIP tag. I think it will cross-compile for Android on macOS/x64 and Win32, but I haven't tried those because I don't have them, so don't know about any incompatibiity there. Try it out and let me know. | 
| Hmm, the config file isn't generated if only the runtime is built and can't always be modified, say if part of a system package. Push that for later, this PR is ready to merge. | 
| Sorry for all the nitpicks, but what do you think about reversing the order to  | 
| Makes sense, that's actually how I wrote it in the help text for  | 
| Thanks! | 
| "-DRT_CFLAGS=" ~ config.cFlags.join(" "), | ||
| "-DLD_FLAGS=" ~ config.linkerFlags.join(" "), | ||
| ]; | ||
| if(config.targetPreset.matchFirst("^Android")) | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine like that, but FYI, std.algorithm.startsWith would also work.
|  | ||
| if(LDC_TARGET_PRESET MATCHES "arm") | ||
| set(TARGET_ARCH "arm") | ||
| set(LLVM_TARGET_TRIPLE "armv7-none-linux-android") | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the -mcpu=cortex-a8 not required anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is, but only for llvm 5.0. I figured that since we're shipping 1.4 with 4.0.1, I'll worry about that later.
… cross-compilation targets tried by the ldc developers, starting with Android-arm and Android-aarch64.
The idea here is to be able to simply specify a dash-separated OS and CPU architecture and our CMake config will try to fill in the rest for you. Probably best to stick this in another CMake file, where we can have common flags for all the cross-compilation platforms the ldc devs have tried out, ie Linux/PPC, Windows/AArch64, or whatever else. You can always override
RT_CFLAGSandLD_FLAGSby setting them manually, this logic will simply supply defaults for when the user doesn't.Android is a little weird because CMake doesn't automatically detect if you're natively compiling on Android, and I can't set
CMAKE_SYSTEM_NAME=Androidbecause it will try to invoke the cross-compilation NDK toolchain. Basically, Android native compilation is unsupported by CMake, to the point where it just assumes cross-compilation and complains that it can't find the NDK.Here are the commands I use to configure CMake for Android/ARM with this PR: note that I have to specify
TARGET_PLATFORMLDC_TARGET_PRESETfor native compilation too, because CMake just thinks native Android/ARM is Linux/ARM. These are the two use cases this PR currently supports, either natively compiling in the Termux Android app (tested by building ldc and running the druntime tests), or cross-compiling from linux/x64 (tested by building ldc and the druntime tests).Native compilation
Cross-compilation from linux/x64
What I'm looking for right now with this incomplete PR is what other ldc devs think of this approach, before I spend more time fleshing it out and adding flags for other architectures like Android-aarch64. For example, it currently assumes you're cross-compiling from linux/x64 using that NDK, whereas we'll need to support Windows/Mac too. I don't know if it's worth setting
CMAKE_CROSSCOMPILING=True, which we haven't used yet, especially because ldc isn't cross-compiled so it may confuse CMake.