Skip to content

Commit 5fa8e0d

Browse files
authored
Add musl libc CI using Alpine Linux container on Ubuntu GHA (#4650)
* 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)
1 parent 09e1822 commit 5fa8e0d

File tree

4 files changed

+163
-15
lines changed

4 files changed

+163
-15
lines changed

.github/workflows/alpine_musl.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: Alpine Linux (musl libc)
2+
on:
3+
- pull_request
4+
- push
5+
6+
concurrency:
7+
group: ${{ github.workflow }}-${{ github.ref }}
8+
cancel-in-progress: true
9+
10+
jobs:
11+
test:
12+
name: Alpine Linux (musl libc)
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
submodules: true
18+
fetch-depth: 50
19+
20+
- name: Setup latest Alpine Linux
21+
uses: jirutka/setup-alpine@v1
22+
with:
23+
branch: v3.20
24+
packages: ldc git g++ cmake ninja llvm-dev llvm-static compiler-rt libunwind-static libxml2-static zstd-static zlib-static bash grep diffutils make
25+
26+
- name: Build LDC bootstrap
27+
shell: alpine.sh {0}
28+
run: |
29+
ninja --version
30+
set -eux
31+
mkdir bootstrap
32+
cd bootstrap
33+
cmake -G Ninja .. \
34+
-DCMAKE_BUILD_TYPE=Release \
35+
-DCMAKE_INSTALL_PREFIX="/opt/ldc2" \
36+
-DCMAKE_EXE_LINKER_FLAGS=-static-libstdc++ \
37+
-DD_COMPILER_FLAGS=-link-defaultlib-shared=false \
38+
-DBUILD_SHARED_LIBS=OFF
39+
ninja obj/ldc2.o all
40+
bin/ldc2 --version
41+
cd ..
42+
43+
# TODO: Add '-DLLVM_IS_SHARED=OFF' when static linking is fully supported
44+
# TSan and XRay do not work.
45+
- name: Build LDC & LDC D unittests & defaultlib unittest runners
46+
shell: alpine.sh {0}
47+
run: |
48+
set -eux
49+
cmake -G Ninja . \
50+
-DD_COMPILER=./bootstrap/bin/ldmd2 \
51+
-DCMAKE_BUILD_TYPE=Release \
52+
-DCMAKE_INSTALL_PREFIX="/opt/ldc2" \
53+
-DCMAKE_EXE_LINKER_FLAGS=-static-libstdc++ \
54+
-DD_COMPILER_FLAGS=-link-defaultlib-shared=false \
55+
-DBUILD_SHARED_LIBS=OFF \
56+
-DTEST_COMPILER_RT_LIBRARIES="profile;lsan;asan;msan;fuzzer"
57+
ninja obj/ldc2.o all ldc2-unittest all-test-runners
58+
bin/ldc2 --version
59+
ldd bin/ldc2
60+
61+
- name: Run LDC D unittests
62+
if: success() || failure()
63+
shell: alpine.sh {0}
64+
run: ctest --output-on-failure -R "ldc2-unittest"
65+
66+
- name: Run LIT testsuite
67+
if: success() || failure()
68+
shell: alpine.sh {0}
69+
run: |
70+
set -eux
71+
ctest -V -R "lit-tests"
72+
73+
- name: Run DMD testsuite
74+
if: success() || failure()
75+
shell: alpine.sh {0}
76+
run: ctest -V -R "dmd-testsuite"
77+
78+
- name: Run defaultlib unittests & druntime integration tests
79+
if: success() || failure()
80+
shell: alpine.sh {0}
81+
run: |
82+
set -eux
83+
ctest -j$(nproc) --output-on-failure -E "dmd-testsuite|lit-tests|ldc2-unittest"

driver/linker-gcc.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -257,23 +257,33 @@ std::string getCompilerRTLibFilename(const llvm::Twine &name,
257257

258258
// Clang's RT libs are in a subdir of the lib dir.
259259
// E.g., for name="libclang_rt.asan" and sharedLibrary=true, returns
260-
// "clang/6.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" on
260+
// "clang/6.0.0/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" and
261+
// "clang/6/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" on
261262
// Darwin.
262263
// This function is "best effort", the path may not be what Clang does...
263264
// See clang/lib/Driver/Toolchain.cpp.
264-
std::string getRelativeClangCompilerRTLibPath(const llvm::Twine &name,
265-
const llvm::Triple &triple,
266-
bool sharedLibrary) {
267-
llvm::StringRef OSName =
268-
triple.isOSDarwin()
269-
? "darwin"
270-
: triple.isOSFreeBSD() ? "freebsd" : triple.getOSName();
265+
std::vector<std::string> getRelativeClangCompilerRTLibPath(
266+
const llvm::Twine &name, const llvm::Triple &triple, bool sharedLibrary) {
267+
llvm::StringRef OSName = triple.isOSDarwin() ? "darwin"
268+
: triple.isOSFreeBSD() ? "freebsd"
269+
: triple.getOSName();
270+
271+
auto llvm_major_version =
272+
llvm::StringRef(ldc::llvm_version_base).take_until([](char c) {
273+
return c == '.';
274+
});
271275

272276
std::string relPath = (llvm::Twine("clang/") + ldc::llvm_version_base +
273277
"/lib/" + OSName + "/" + name)
274278
.str();
279+
std::string relPath_llvm_major_version =
280+
(llvm::Twine("clang/") + llvm_major_version + "/lib/" + OSName + "/" +
281+
name)
282+
.str();
275283

276-
return getCompilerRTLibFilename(relPath, triple, sharedLibrary);
284+
return {getCompilerRTLibFilename(relPath, triple, sharedLibrary),
285+
getCompilerRTLibFilename(relPath_llvm_major_version, triple,
286+
sharedLibrary)};
277287
}
278288

279289
void appendFullLibPathCandidates(std::vector<std::string> &paths,
@@ -299,7 +309,8 @@ void appendFullLibPathCandidates(std::vector<std::string> &paths,
299309
// E.g., for baseName="asan" and sharedLibrary=false, returns something like
300310
// [ "<libDir>/libldc_rt.asan.a",
301311
// "<libDir>/libclang_rt.asan_osx.a",
302-
// "<libDir>/clang/6.0.0/lib/darwin/libclang_rt.asan_osx.a" ].
312+
// "<libDir>/clang/6.0.0/lib/darwin/libclang_rt.asan_osx.a",
313+
// "<libDir>/clang/6/lib/darwin/libclang_rt.asan_osx.a" ].
303314
std::vector<std::string>
304315
getFullCompilerRTLibPathCandidates(llvm::StringRef baseName,
305316
const llvm::Triple &triple,
@@ -315,7 +326,9 @@ getFullCompilerRTLibPathCandidates(llvm::StringRef baseName,
315326
appendFullLibPathCandidates(r, clangRT);
316327
const auto fullClangRT = getRelativeClangCompilerRTLibPath(
317328
"libclang_rt." + baseName, triple, sharedLibrary);
318-
appendFullLibPathCandidates(r, fullClangRT);
329+
for (const auto &path : fullClangRT) {
330+
appendFullLibPathCandidates(r, path);
331+
}
319332
return r;
320333
}
321334

runtime/druntime/src/core/sys/posix/sys/statvfs.d

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,57 @@ version (CRuntime_Glibc) {
8484
int statvfs (const char * file, statvfs_t* buf);
8585
int fstatvfs (int fildes, statvfs_t *buf);
8686
}
87+
}
88+
else version (CRuntime_Musl)
89+
{
90+
struct statvfs_t
91+
{
92+
c_ulong f_bsize;
93+
c_ulong f_frsize;
94+
fsblkcnt_t f_blocks;
95+
fsblkcnt_t f_bfree;
96+
fsblkcnt_t f_bavail;
97+
fsfilcnt_t f_files;
98+
fsfilcnt_t f_ffree;
99+
fsfilcnt_t f_favail;
100+
static if (true /+__BYTE_ORDER == __LITTLE_ENDIAN+/)
101+
{
102+
c_ulong f_fsid;
103+
byte[2*int.sizeof-c_long.sizeof] __padding;
104+
}
105+
else
106+
{
107+
byte[2*int.sizeof-c_long.sizeof] __padding;
108+
c_ulong f_fsid;
109+
}
110+
c_ulong f_flag;
111+
c_ulong f_namemax;
112+
uint f_type;
113+
int[5] __reserved;
114+
}
115+
116+
enum FFlag
117+
{
118+
ST_RDONLY = 1, /* Mount read-only. */
119+
ST_NOSUID = 2,
120+
ST_NODEV = 4, /* Disallow access to device special files. */
121+
ST_NOEXEC = 8, /* Disallow program execution. */
122+
ST_SYNCHRONOUS = 16, /* Writes are synced at once. */
123+
ST_MANDLOCK = 64, /* Allow mandatory locks on an FS. */
124+
ST_WRITE = 128, /* Write on file/directory/symlink. */
125+
ST_APPEND = 256, /* Append-only file. */
126+
ST_IMMUTABLE = 512, /* Immutable file. */
127+
ST_NOATIME = 1024, /* Do not update access times. */
128+
ST_NODIRATIME = 2048, /* Do not update directory access times. */
129+
ST_RELATIME = 4096 /* Update atime relative to mtime/ctime. */
130+
131+
}
132+
133+
int statvfs (const char * file, statvfs_t* buf);
134+
int fstatvfs (int fildes, statvfs_t *buf);
87135

136+
alias statvfs statvfs64;
137+
alias fstatvfs fstatvfs64;
88138
}
89139
else version (NetBSD)
90140
{

tests/dmd/CMakeLists.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ endif()
77
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
88
set(gdb_result_code)
99
execute_process(COMMAND gdb --version
10-
COMMAND head -n 1
11-
RESULT_VARIABLE gdb_result_code
12-
OUTPUT_VARIABLE GDB_VERSION
13-
OUTPUT_STRIP_TRAILING_WHITESPACE)
10+
RESULT_VARIABLE gdb_result_code)
1411
if(gdb_result_code)
1512
message(STATUS "GDB not detected, will exclude GDB tests from test suite")
1613
set(gdb_flags "OFF")
1714
else()
15+
execute_process(COMMAND gdb --version
16+
COMMAND head -n 1
17+
RESULT_VARIABLE gdb_result_code
18+
OUTPUT_VARIABLE GDB_VERSION
19+
OUTPUT_STRIP_TRAILING_WHITESPACE)
1820
string(REGEX REPLACE "[^0-9]*([0-9]+[0-9.]*).*" "\\1" GDB_VERSION "${GDB_VERSION}")
1921
message(STATUS "GDB ${GDB_VERSION} detected")
2022
set(gdb_flags "ON")

0 commit comments

Comments
 (0)