Difference between revisions of "Building LDC runtime libraries"

From D Wiki
Jump to: navigation, search
m (Basic usage)
m (Usage for cross-compilation: Somewhat modernize Android and Apple examples)
 
(10 intermediate revisions by 3 users not shown)
Line 29: Line 29:
  
 
<pre>
 
<pre>
ldc-build-runtime [--ninja] [-j4] [--testrunners] [--targetPreset=…] [--dFlags=…] [--cFlags=…] [--linkerFlags=…] [CMAKE_VAR1=value1] [CMAKE_VAR2=value2 …]
+
ldc-build-runtime [--ninja] [-j4] [--testrunners] [--dFlags=…] [--cFlags=…] [--linkerFlags=…] [CMAKE_VAR1=value1] [CMAKE_VAR2=value2 …]
 
</pre>
 
</pre>
  
Line 37: Line 37:
 
ldc-build-runtime --ninja --dFlags="-flto=thin" BUILD_SHARED_LIBS=OFF
 
ldc-build-runtime --ninja --dFlags="-flto=thin" BUILD_SHARED_LIBS=OFF
 
</pre>
 
</pre>
 +
 +
== Solution for common problems ==
 +
 +
<li>Cannot check C compiler(CMakeTestCCompiler): Add '''CMAKE_C_COMPILER_WORKS=1''' and it will skip the C compiler check. </li>
  
 
== Usage for cross-compilation ==
 
== Usage for cross-compilation ==
  
<pre>
+
<syntaxhighlight lang=bash>
 
CC=cross-gcc ldc-build-runtime [--ninja] [-j4] [--testrunners] --dFlags="-mtriple=…;…" [--cFlags=…] [--linkerFlags=…] --targetSystem=… …
 
CC=cross-gcc ldc-build-runtime [--ninja] [-j4] [--testrunners] --dFlags="-mtriple=…;…" [--cFlags=…] [--linkerFlags=…] --targetSystem=… …
</pre>
+
</syntaxhighlight>
  
 
For example, to cross-compile from linux/x64 with glibc to an Alpine linux/x64 container just requires specifying a C cross-compiler and a different cross-compilation triple (install the clang and musl packages in Arch linux to try this out):
 
For example, to cross-compile from linux/x64 with glibc to an Alpine linux/x64 container just requires specifying a C cross-compiler and a different cross-compilation triple (install the clang and musl packages in Arch linux to try this out):
  
<pre>
+
<syntaxhighlight lang=bash>
CC=musl-clang ldc-build-runtime --dFlags="-w;-mtriple=x86_64-alpine-linux-musl"</pre>
+
CC=musl-clang ldc-build-runtime --dFlags="-mtriple=x86_64-alpine-linux-musl"
 +
</syntaxhighlight>
  
 
From Linux/x86_64 to Linux/ARM:
 
From Linux/x86_64 to Linux/ARM:
  
<pre>
+
<syntaxhighlight lang=bash>
CC=arm-linux-gnueabihf-gcc ldc-build-runtime --ninja --dFlags="-w;-mtriple=arm-linux-gnueabihf" --targetSystem="Linux;UNIX"  
+
CC=arm-linux-gnueabihf-gcc ldc-build-runtime --ninja --dFlags="-mtriple=arm-linux-gnueabihf"
</pre>
+
</syntaxhighlight>
 +
 
 +
or to Linux/AArch64, ie 64-bit ARM (here using the <tt>aarch64-linux-gnu-gcc</tt> package in Arch linux):
 +
 
 +
<syntaxhighlight lang=bash>
 +
CC=aarch64-linux-gnu-gcc ldc-build-runtime --ninja --dFlags="-mtriple=aarch64-none-linux-gnu"
 +
</syntaxhighlight>
  
 
or to Linux/MIPS32:
 
or to Linux/MIPS32:
  
<pre>
+
<syntaxhighlight lang=bash>
CC=mipsel-linux-gcc ldc-build-runtime --ninja --dFlags="-w;-mtriple=mipsel-linux;-mcpu=mips32" --cFlags="-march=mips32" --targetSystem="Linux;UNIX"
+
CC=mipsel-linux-gcc ldc-build-runtime --ninja --dFlags="-mtriple=mipsel-linux;-mcpu=mips32" --cFlags="-march=mips32"
</pre>
+
</syntaxhighlight>
  
 
From Windows to Linux/ARM, e.g., by using an official [http://gnutoolchains.com/raspberry/ Raspberry PI toolchain]:
 
From Windows to Linux/ARM, e.g., by using an official [http://gnutoolchains.com/raspberry/ Raspberry PI toolchain]:
  
<pre>
+
<syntaxhighlight lang=bash>
 
set CC=arm-linux-gnueabihf-gcc
 
set CC=arm-linux-gnueabihf-gcc
ldc-build-runtime --ninja --dFlags=-w;-mtriple=arm-linux-gnueabihf --targetSystem=Linux;UNIX CMAKE_SYSTEM_NAME=Linux CMAKE_C_COMPILER_WORKS=True BUILD_SHARED_LIBS=OFF
+
ldc-build-runtime --ninja --dFlags=-mtriple=arm-linux-gnueabihf --targetSystem=Linux;UNIX CMAKE_SYSTEM_NAME=Linux CMAKE_C_COMPILER_WORKS=True BUILD_SHARED_LIBS=OFF
</pre>
+
</syntaxhighlight>
 +
 
 +
From Linux, Mac or Windows to Android/AArch64, assuming the [https://developer.android.com/ndk/downloads Android NDK] r26d has been unzipped into <tt>/home/me</tt>:
 +
 
 +
<syntaxhighlight lang=bash>
 +
ldc-build-runtime --ninja \
 +
                  --dFlags="-mtriple=aarch64-linux-android30" \
 +
                  --targetSystem="Android;Linux;UNIX" \
 +
                  CMAKE_TOOLCHAIN_FILE="/home/me/android-ndk-r26d/build/cmake/android.toolchain.cmake" \
 +
                  ANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF \
 +
                  ANDROID_ABI=arm64-v8a \
 +
                  ANDROID_NATIVE_API_LEVEL=30
 +
</syntaxhighlight>
 +
 
 +
Check out the official [https://developer.android.com/ndk/guides/cmake Android NDK CMake guide] for possible values of the <tt>ANDROID_*</tt> variables, e.g., to target other architectures (and make sure to adapt the <tt>-mtriple</tt> flag in that case). For full instructions on Android cross-compilation, [[Build D for Android|see the Android page]]. It also shows examples of using ldc with the newly generated runtime libraries to compile your own code.
 +
 
 +
From macOS/x64 to macOS/arm64:
  
Cross-compiling to Android/ARM using the Android NDK is more involved, so LDC features a [https://github.com/ldc-developers/ldc/blob/master/runtime/PresetRuntimeConfiguration.cmake target configuration preset for Android]. On Linux/x86_64, set the path to your NDK's C cross-compiler and simply specify the Android target configuration which has been preset for you, while still being able to override the C and linker flags or append your own D flags, by passing those flags in yourself:
+
<syntaxhighlight lang=bash>
 +
ldc-build-runtime --ninja \
 +
                  --dFlags="-mtriple=arm64-apple-macos11.0" \
 +
                  CMAKE_OSX_ARCHITECTURES=arm64 \
 +
                  CMAKE_OSX_DEPLOYMENT_TARGET=11.0
 +
</syntaxhighlight>
  
<pre>
+
or to iOS/arm64:
export CC=/path/to/your/android-ndk-r15c/toolchains/llvm/prebuilt/linux-x86_64/bin/clang
 
ldc-build-runtime [--ninja] [--testrunners] --targetPreset=Android-arm
 
</pre>
 
  
For full instructions on Android cross-compilation, including using ldc-build-runtime from Windows, [[Build D for Android|see the Android page]]. It also shows examples of using ldc with the newly generated runtime libraries to compile your own code.
+
<syntaxhighlight lang=bash>
 +
ldc-build-runtime --ninja \
 +
                  --dFlags="-mtriple=arm64-apple-ios12.0" \
 +
                  CMAKE_SYSTEM_NAME=iOS \
 +
                  CMAKE_OSX_ARCHITECTURES=arm64 \
 +
                  CMAKE_OSX_DEPLOYMENT_TARGET=12.0
 +
</syntaxhighlight>
 
   
 
   
 
[[Category:LDC]]
 
[[Category:LDC]]

Latest revision as of 20:40, 21 May 2024

Starting with version 1.4, LDC ships with a small build tool to allow you to recompile the D runtime and standard library (and optionally the accompanying testrunners) the way you want, ldc-build-runtime.

Use cases

  • Link-Time Optimization (LTO) for the runtime libraries by recompiling with -flto, which produces smaller binaries and may show significant performance gains
  • Adding sanitizer checks via -fsanitize
  • Cross-compilation for other platforms, as the D runtime and standard library must be generated for your target platform before you can cross-compile and link D executables and shared libraries

Prerequisites

  • CMake
  • Either Make, the default, or Ninja (recommended, enable with --ninja)
  • C toolchain (compiler, linker and libraries): gcc, clang, Microsoft Visual C++, …

How it works

If run without special command-line options, ldc-build-runtime automates:

  • Creating a build directory
  • Downloading & extracting the LDC source archive matching the LDC version
  • Invoking CMake to generate the Make or Ninja build script for the runtime libraries
  • Calling Make or Ninja to build the runtime libraries

The runtime libraries end up in the lib subdirectory of the build directory, i.e. ./ldc-build-runtime.tmp/lib by default. You can replace your existing LDC runtime libraries or link against the new libraries by specifying their directory in the LDC command line: ldc2 … -L-L/path/to/ldc-build-runtime.tmp/lib.

Basic usage

The primary aim is to allow specifying additional compiler/linker command-line options and customizing CMake variables.
Run ldc-build-runtime -h for the full list of command-line options.

ldc-build-runtime [--ninja] [-j4] [--testrunners] [--dFlags=…] [--cFlags=…] [--linkerFlags=…] [CMAKE_VAR1=value1] [CMAKE_VAR2=value2 …]

For example, to prepare for link-time optimization between your user code and the static runtime libraries, you can recompile the runtime libraries with:

ldc-build-runtime --ninja --dFlags="-flto=thin" BUILD_SHARED_LIBS=OFF

Solution for common problems

  • Cannot check C compiler(CMakeTestCCompiler): Add CMAKE_C_COMPILER_WORKS=1 and it will skip the C compiler check.
  • Usage for cross-compilation

    CC=cross-gcc ldc-build-runtime [--ninja] [-j4] [--testrunners] --dFlags="-mtriple=…;…" [--cFlags=] [--linkerFlags=] --targetSystem=… …
    

    For example, to cross-compile from linux/x64 with glibc to an Alpine linux/x64 container just requires specifying a C cross-compiler and a different cross-compilation triple (install the clang and musl packages in Arch linux to try this out):

    CC=musl-clang ldc-build-runtime --dFlags="-mtriple=x86_64-alpine-linux-musl"
    

    From Linux/x86_64 to Linux/ARM:

    CC=arm-linux-gnueabihf-gcc ldc-build-runtime --ninja --dFlags="-mtriple=arm-linux-gnueabihf"
    

    or to Linux/AArch64, ie 64-bit ARM (here using the aarch64-linux-gnu-gcc package in Arch linux):

    CC=aarch64-linux-gnu-gcc ldc-build-runtime --ninja --dFlags="-mtriple=aarch64-none-linux-gnu"
    

    or to Linux/MIPS32:

    CC=mipsel-linux-gcc ldc-build-runtime --ninja --dFlags="-mtriple=mipsel-linux;-mcpu=mips32" --cFlags="-march=mips32"
    

    From Windows to Linux/ARM, e.g., by using an official Raspberry PI toolchain:

    set CC=arm-linux-gnueabihf-gcc
    ldc-build-runtime --ninja --dFlags=-mtriple=arm-linux-gnueabihf --targetSystem=Linux;UNIX CMAKE_SYSTEM_NAME=Linux CMAKE_C_COMPILER_WORKS=True BUILD_SHARED_LIBS=OFF
    

    From Linux, Mac or Windows to Android/AArch64, assuming the Android NDK r26d has been unzipped into /home/me:

    ldc-build-runtime --ninja \
                      --dFlags="-mtriple=aarch64-linux-android30" \
                      --targetSystem="Android;Linux;UNIX" \
                      CMAKE_TOOLCHAIN_FILE="/home/me/android-ndk-r26d/build/cmake/android.toolchain.cmake" \
                      ANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF \
                      ANDROID_ABI=arm64-v8a \
                      ANDROID_NATIVE_API_LEVEL=30
    

    Check out the official Android NDK CMake guide for possible values of the ANDROID_* variables, e.g., to target other architectures (and make sure to adapt the -mtriple flag in that case). For full instructions on Android cross-compilation, see the Android page. It also shows examples of using ldc with the newly generated runtime libraries to compile your own code.

    From macOS/x64 to macOS/arm64:

    ldc-build-runtime --ninja \
                      --dFlags="-mtriple=arm64-apple-macos11.0" \
                      CMAKE_OSX_ARCHITECTURES=arm64 \
                      CMAKE_OSX_DEPLOYMENT_TARGET=11.0
    

    or to iOS/arm64:

    ldc-build-runtime --ninja \
                      --dFlags="-mtriple=arm64-apple-ios12.0" \
                      CMAKE_SYSTEM_NAME=iOS \
                      CMAKE_OSX_ARCHITECTURES=arm64 \
                      CMAKE_OSX_DEPLOYMENT_TARGET=12.0