Skip to content

Commit

Permalink
Add musl libc CI using Alpine Linux container on Ubuntu GHA (#4650)
Browse files Browse the repository at this point in the history
* Add musl libc CI on Alpine Linux

* Fix gdb detection.
The pipe through `head` meant that error code was always 0, even when gdb is absent.

* Try a little harder to find compiler-rt libs, by also searching directory structure with major llvm version instead of x.y.z version.

* Add compiler-rt package

* TSan and XRay do not work on Alpine

* Add correct statvfs_t for Musl (upstreamed)
  • Loading branch information
JohanEngelen authored Jun 29, 2024
1 parent 09e1822 commit 5fa8e0d
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 15 deletions.
83 changes: 83 additions & 0 deletions .github/workflows/alpine_musl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Alpine Linux (musl libc)
on:
- pull_request
- push

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
name: Alpine Linux (musl libc)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 50

- name: Setup latest Alpine Linux
uses: jirutka/setup-alpine@v1
with:
branch: v3.20
packages: ldc git g++ cmake ninja llvm-dev llvm-static compiler-rt libunwind-static libxml2-static zstd-static zlib-static bash grep diffutils make

- name: Build LDC bootstrap
shell: alpine.sh {0}
run: |
ninja --version
set -eux
mkdir bootstrap
cd bootstrap
cmake -G Ninja .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="/opt/ldc2" \
-DCMAKE_EXE_LINKER_FLAGS=-static-libstdc++ \
-DD_COMPILER_FLAGS=-link-defaultlib-shared=false \
-DBUILD_SHARED_LIBS=OFF
ninja obj/ldc2.o all
bin/ldc2 --version
cd ..
# TODO: Add '-DLLVM_IS_SHARED=OFF' when static linking is fully supported
# TSan and XRay do not work.
- name: Build LDC & LDC D unittests & defaultlib unittest runners
shell: alpine.sh {0}
run: |
set -eux
cmake -G Ninja . \
-DD_COMPILER=./bootstrap/bin/ldmd2 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="/opt/ldc2" \
-DCMAKE_EXE_LINKER_FLAGS=-static-libstdc++ \
-DD_COMPILER_FLAGS=-link-defaultlib-shared=false \
-DBUILD_SHARED_LIBS=OFF \
-DTEST_COMPILER_RT_LIBRARIES="profile;lsan;asan;msan;fuzzer"
ninja obj/ldc2.o all ldc2-unittest all-test-runners
bin/ldc2 --version
ldd bin/ldc2
- name: Run LDC D unittests
if: success() || failure()
shell: alpine.sh {0}
run: ctest --output-on-failure -R "ldc2-unittest"

- name: Run LIT testsuite
if: success() || failure()
shell: alpine.sh {0}
run: |
set -eux
ctest -V -R "lit-tests"
- name: Run DMD testsuite
if: success() || failure()
shell: alpine.sh {0}
run: ctest -V -R "dmd-testsuite"

- name: Run defaultlib unittests & druntime integration tests
if: success() || failure()
shell: alpine.sh {0}
run: |
set -eux
ctest -j$(nproc) --output-on-failure -E "dmd-testsuite|lit-tests|ldc2-unittest"
35 changes: 24 additions & 11 deletions driver/linker-gcc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,23 +257,33 @@ std::string getCompilerRTLibFilename(const llvm::Twine &name,

// Clang's RT libs are in a subdir of the lib dir.
// E.g., for name="libclang_rt.asan" and sharedLibrary=true, returns
// "clang/6.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" on
// "clang/6.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" and
// "clang/6/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" on
// Darwin.
// This function is "best effort", the path may not be what Clang does...
// See clang/lib/Driver/Toolchain.cpp.
std::string getRelativeClangCompilerRTLibPath(const llvm::Twine &name,
const llvm::Triple &triple,
bool sharedLibrary) {
llvm::StringRef OSName =
triple.isOSDarwin()
? "darwin"
: triple.isOSFreeBSD() ? "freebsd" : triple.getOSName();
std::vector<std::string> getRelativeClangCompilerRTLibPath(
const llvm::Twine &name, const llvm::Triple &triple, bool sharedLibrary) {
llvm::StringRef OSName = triple.isOSDarwin() ? "darwin"
: triple.isOSFreeBSD() ? "freebsd"
: triple.getOSName();

auto llvm_major_version =
llvm::StringRef(ldc::llvm_version_base).take_until([](char c) {
return c == '.';
});

std::string relPath = (llvm::Twine("clang/") + ldc::llvm_version_base +
"/lib/" + OSName + "/" + name)
.str();
std::string relPath_llvm_major_version =
(llvm::Twine("clang/") + llvm_major_version + "/lib/" + OSName + "/" +
name)
.str();

return getCompilerRTLibFilename(relPath, triple, sharedLibrary);
return {getCompilerRTLibFilename(relPath, triple, sharedLibrary),
getCompilerRTLibFilename(relPath_llvm_major_version, triple,
sharedLibrary)};
}

void appendFullLibPathCandidates(std::vector<std::string> &paths,
Expand All @@ -299,7 +309,8 @@ void appendFullLibPathCandidates(std::vector<std::string> &paths,
// E.g., for baseName="asan" and sharedLibrary=false, returns something like
// [ "<libDir>/libldc_rt.asan.a",
// "<libDir>/libclang_rt.asan_osx.a",
// "<libDir>/clang/6.0.0/lib/darwin/libclang_rt.asan_osx.a" ].
// "<libDir>/clang/6.0.0/lib/darwin/libclang_rt.asan_osx.a",
// "<libDir>/clang/6/lib/darwin/libclang_rt.asan_osx.a" ].
std::vector<std::string>
getFullCompilerRTLibPathCandidates(llvm::StringRef baseName,
const llvm::Triple &triple,
Expand All @@ -315,7 +326,9 @@ getFullCompilerRTLibPathCandidates(llvm::StringRef baseName,
appendFullLibPathCandidates(r, clangRT);
const auto fullClangRT = getRelativeClangCompilerRTLibPath(
"libclang_rt." + baseName, triple, sharedLibrary);
appendFullLibPathCandidates(r, fullClangRT);
for (const auto &path : fullClangRT) {
appendFullLibPathCandidates(r, path);
}
return r;
}

Expand Down
50 changes: 50 additions & 0 deletions runtime/druntime/src/core/sys/posix/sys/statvfs.d
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,57 @@ version (CRuntime_Glibc) {
int statvfs (const char * file, statvfs_t* buf);
int fstatvfs (int fildes, statvfs_t *buf);
}
}
else version (CRuntime_Musl)
{
struct statvfs_t
{
c_ulong f_bsize;
c_ulong f_frsize;
fsblkcnt_t f_blocks;
fsblkcnt_t f_bfree;
fsblkcnt_t f_bavail;
fsfilcnt_t f_files;
fsfilcnt_t f_ffree;
fsfilcnt_t f_favail;
static if (true /+__BYTE_ORDER == __LITTLE_ENDIAN+/)
{
c_ulong f_fsid;
byte[2*int.sizeof-c_long.sizeof] __padding;
}
else
{
byte[2*int.sizeof-c_long.sizeof] __padding;
c_ulong f_fsid;
}
c_ulong f_flag;
c_ulong f_namemax;
uint f_type;
int[5] __reserved;
}

enum FFlag
{
ST_RDONLY = 1, /* Mount read-only. */
ST_NOSUID = 2,
ST_NODEV = 4, /* Disallow access to device special files. */
ST_NOEXEC = 8, /* Disallow program execution. */
ST_SYNCHRONOUS = 16, /* Writes are synced at once. */
ST_MANDLOCK = 64, /* Allow mandatory locks on an FS. */
ST_WRITE = 128, /* Write on file/directory/symlink. */
ST_APPEND = 256, /* Append-only file. */
ST_IMMUTABLE = 512, /* Immutable file. */
ST_NOATIME = 1024, /* Do not update access times. */
ST_NODIRATIME = 2048, /* Do not update directory access times. */
ST_RELATIME = 4096 /* Update atime relative to mtime/ctime. */

}

int statvfs (const char * file, statvfs_t* buf);
int fstatvfs (int fildes, statvfs_t *buf);

alias statvfs statvfs64;
alias fstatvfs fstatvfs64;
}
else version (NetBSD)
{
Expand Down
10 changes: 6 additions & 4 deletions tests/dmd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(gdb_result_code)
execute_process(COMMAND gdb --version
COMMAND head -n 1
RESULT_VARIABLE gdb_result_code
OUTPUT_VARIABLE GDB_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
RESULT_VARIABLE gdb_result_code)
if(gdb_result_code)
message(STATUS "GDB not detected, will exclude GDB tests from test suite")
set(gdb_flags "OFF")
else()
execute_process(COMMAND gdb --version
COMMAND head -n 1
RESULT_VARIABLE gdb_result_code
OUTPUT_VARIABLE GDB_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REGEX REPLACE "[^0-9]*([0-9]+[0-9.]*).*" "\\1" GDB_VERSION "${GDB_VERSION}")
message(STATUS "GDB ${GDB_VERSION} detected")
set(gdb_flags "ON")
Expand Down

0 comments on commit 5fa8e0d

Please # to comment.