Skip to content

Commit f131b79

Browse files
author
William Yang
committed
fix: use static linking for libcs50 to avoid runtime library issues
- Add STATIC_LIBS mapping for libraries that should be statically linked - _find_static_lib() searches LIB_PATHS for .a files - Replaces -lcs50 with /usr/local/lib/libcs50.a at compile time - Eliminates dyld library loading errors on macOS
1 parent e38bfbc commit f131b79

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

bootcs/check/c.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
Licensed under GPL-3.0
66
"""
77

8+
import os
9+
import platform
810
import re
911
import tempfile
1012
from pathlib import Path
@@ -25,6 +27,24 @@ def _(s):
2527
#: Default CFLAGS for compile()
2628
CFLAGS = {"std": "c11", "ggdb": True, "lm": True}
2729

30+
#: Library paths to search for static/dynamic libraries
31+
LIB_PATHS = ["/usr/local/lib", "/opt/homebrew/lib"]
32+
33+
#: Static libraries to prefer (avoids runtime dynamic library issues)
34+
#: Format: flag_name -> static_library_filename
35+
STATIC_LIBS = {
36+
"lcs50": "libcs50.a",
37+
}
38+
39+
40+
def _find_static_lib(lib_name):
41+
"""Find static library file path, return None if not found."""
42+
for lib_path in LIB_PATHS:
43+
static_path = os.path.join(lib_path, lib_name)
44+
if os.path.isfile(static_path):
45+
return static_path
46+
return None
47+
2848

2949
def compile(*files, exe_name=None, cc=CC, max_log_lines=50, **cflags):
3050
"""
@@ -53,7 +73,37 @@ def compile(*files, exe_name=None, cc=CC, max_log_lines=50, **cflags):
5373

5474
out_flag = f" -o {exe_name} " if exe_name is not None else " "
5575

56-
process = run(f"{cc} {files_str}{out_flag}{flags}")
76+
# Check for static libraries to use instead of dynamic ones
77+
# This avoids runtime library loading issues on different systems
78+
static_lib_flags = ""
79+
remaining_flags = []
80+
81+
for flag, value in list(flags.items()) if isinstance(flags, dict) else []:
82+
pass # flags is already a string at this point
83+
84+
# Parse flags string and replace -lXXX with static library paths where available
85+
flag_parts = flags.split()
86+
final_flags = []
87+
for part in flag_parts:
88+
if part.startswith("-l"):
89+
lib_flag = part[1:] # e.g., "lcs50"
90+
if lib_flag in STATIC_LIBS:
91+
static_lib = _find_static_lib(STATIC_LIBS[lib_flag])
92+
if static_lib:
93+
static_lib_flags += f" {static_lib}"
94+
continue # Skip this flag, use static lib instead
95+
final_flags.append(part)
96+
97+
flags = " ".join(final_flags)
98+
99+
# Add library paths for any remaining dynamic libraries
100+
lib_flags = ""
101+
for lib_path in LIB_PATHS:
102+
if os.path.isdir(lib_path):
103+
lib_flags += f" -L{lib_path}"
104+
break # Use first available path
105+
106+
process = run(f"{cc} {files_str}{out_flag}{flags}{lib_flags}{static_lib_flags}")
57107

58108
# Strip out ANSI codes
59109
stdout = re.sub(r"\x1B\[[0-?]*[ -/]*[@-~]", "", process.stdout())

0 commit comments

Comments
 (0)