Skip to content

Commit

Permalink
Implement -framework FrameworkName on macOS
Browse files Browse the repository at this point in the history
  • Loading branch information
Jarred-Sumner committed Sep 17, 2024
1 parent ab63136 commit 4a78fc1
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 1 deletion.
7 changes: 7 additions & 0 deletions libtcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,8 @@ LIBTCCAPI void tcc_delete(TCCState *s1)
tcc_free(s1->deps_outfile);
#if defined TCC_TARGET_MACHO
tcc_free(s1->install_name);
dynarray_reset(&s1->framework_names, &s1->nb_framework_names);
dynarray_reset(&s1->framework_search_paths, &s1->nb_framework_search_paths);
#endif
dynarray_reset(&s1->files, &s1->nb_files);
dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
Expand Down Expand Up @@ -1598,6 +1600,7 @@ enum {
TCC_OPTION_mfloat_abi,
TCC_OPTION_m,
TCC_OPTION_f,
TCC_OPTION_framework,
TCC_OPTION_isystem,
TCC_OPTION_iwithprefix,
TCC_OPTION_include,
Expand Down Expand Up @@ -1682,6 +1685,7 @@ static const TCCOption tcc_options[] = {
{ "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
#ifdef TCC_TARGET_MACHO
{ "flat_namespace", TCC_OPTION_flat_namespace, 0 },
{ "framework", TCC_OPTION_framework, TCC_OPTION_HAS_ARG },
#endif
{ "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
{ "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
Expand Down Expand Up @@ -2040,6 +2044,9 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
s->option_r = 1;
x = TCC_OUTPUT_OBJ;
goto set_output_type;
case TCC_OPTION_framework:
dynarray_add(&s->framework_names, &s->nb_framework_names, tcc_strdup(optarg));
break;
case TCC_OPTION_isystem:
tcc_add_sysinclude_path(s, optarg);
break;
Expand Down
12 changes: 12 additions & 0 deletions tcc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,17 @@ struct TCCState {
int argc;
char **argv;
CString linker_arg; /* collect -Wl options */

#ifdef TCC_TARGET_MACHO
/* darwin framework names */
char **framework_names;
int nb_framework_names;

/* darwin framework paths */
char **framework_search_paths;
int nb_framework_search_paths;
#endif

};

struct filespec {
Expand Down Expand Up @@ -1774,6 +1785,7 @@ ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev);
ST_FUNC int macho_load_tbd(TCCState *s1, int fd, const char *filename, int lev);
#ifdef TCC_IS_NATIVE
ST_FUNC void tcc_add_macos_sdkpath(TCCState* s);
ST_FUNC char* tcc_search_darwin_framework(TCCState* s, const char* include_name);
ST_FUNC const char* macho_tbd_soname(const char* filename);
#endif
#endif
Expand Down
65 changes: 65 additions & 0 deletions tccmacho.c
Original file line number Diff line number Diff line change
Expand Up @@ -2270,6 +2270,53 @@ static uint32_t macho_swap32(uint32_t x)
char* xcode_select_sdkroot;
bool xcode_select_loaded = false;

ST_FUNC char* tcc_search_darwin_framework(TCCState* s, const char* include_name) {
// "<Security/Security.h>"
// ^
size_t include_name_length = strlen(include_name);
const void* first_slash_identifying_framework_name_in_include_ptr = memchr(include_name, '/', include_name_length);
if (first_slash_identifying_framework_name_in_include_ptr == NULL) {
return 0;
}
size_t first_slash_identifying_framework_name_in_include_index = (const char*)first_slash_identifying_framework_name_in_include_ptr - include_name;
size_t framework_name_length = first_slash_identifying_framework_name_in_include_index;
if (framework_name_length == 0) {
return 0;
}

for (int i = 0; i < s->nb_framework_names; i++) {
const char* current_framework_name = s->framework_names[i];
if (strlen(current_framework_name) != framework_name_length) {
continue;
}
if (strncmp(include_name, current_framework_name, framework_name_length) == 0) {
return s->framework_search_paths[i];
}
}

return 0;
}

ST_FUNC void tcc_add_macos_framework_path(TCCState* s, const char* framework_name, const char* base_path) {
char path_buffer[2048];
pstrcpy(path_buffer, sizeof(path_buffer), base_path);
pstrcat(path_buffer, sizeof(path_buffer), "/System/Library/Frameworks/");
pstrcat(path_buffer, sizeof(path_buffer), framework_name);
pstrcat(path_buffer, sizeof(path_buffer), ".framework/");
// .tbd
pstrcat(path_buffer, sizeof(path_buffer), "Versions/Current/");
pstrcat(path_buffer, sizeof(path_buffer), framework_name);
pstrcat(path_buffer, sizeof(path_buffer), ".tbd");
tcc_add_library_path(s, path_buffer);

// .framework/Headers
pstrcpy(path_buffer, sizeof(path_buffer), base_path);
pstrcat(path_buffer, sizeof(path_buffer), "/System/Library/Frameworks/");
pstrcat(path_buffer, sizeof(path_buffer), framework_name);
pstrcat(path_buffer, sizeof(path_buffer), ".framework/Headers/");
dynarray_add(&s->framework_search_paths, &s->nb_framework_search_paths, tcc_strdup(path_buffer));
}

/* Looks for the active developer SDK set by xcode-select (or the default
one set during installation.) */
ST_FUNC void tcc_add_macos_sdkpath(TCCState* s)
Expand Down Expand Up @@ -2303,6 +2350,24 @@ ST_FUNC void tcc_add_macos_sdkpath(TCCState* s)
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib"
":" "/Applications/Xcode.app/Developer/SDKs/MacOSX.sdk/usr/lib"
);

if (s->nb_framework_names > 0) {
if (xcode_select_sdkroot) {
for (int i = 0; i < s->nb_framework_names; i++) {
tcc_add_macos_framework_path(s, s->framework_names[i], xcode_select_sdkroot);
}
} else {
if (access("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk", F_OK) == 0) {
for (int i = 0; i < s->nb_framework_names; i++) {
tcc_add_macos_framework_path(s, s->framework_names[i], "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk");
}
} else if (access("/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk", F_OK) == 0) {
for (int i = 0; i < s->nb_framework_names; i++) {
tcc_add_macos_framework_path(s, s->framework_names[i], "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk");
}
}
}
}
cstr_free(&path);
}

Expand Down
13 changes: 12 additions & 1 deletion tccpp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1347,7 +1347,7 @@ search_cached_include(TCCState *s1, const char *filename, int add);
static int parse_include(TCCState *s1, int do_next, int test)
{
int c, i;
char name[1024], buf[1024], *p;
char name[1024], buf[1024], *darwin_framework_search_path, *p;
CachedInclude *e;

c = skip_spaces();
Expand Down Expand Up @@ -1402,6 +1402,17 @@ static int parse_include(TCCState *s1, int do_next, int test)
p = s1->sysinclude_paths[k];
else if (test)
return 0;
#ifdef TCC_TARGET_MACHO
else if (s1->nb_framework_names > 0 && (darwin_framework_search_path = tcc_search_darwin_framework(s1, (const char*)name))) {
pstrcpy(buf, sizeof buf, darwin_framework_search_path);
pstrcat(buf, sizeof buf, tcc_basename(name));
if (tcc_open(s1, buf) >= 0) {
break;
} else {
tcc_error("include file '%s' not found", name);
}
}
#endif
else
tcc_error("include file '%s' not found", name);
pstrcpy(buf, sizeof buf, p);
Expand Down

0 comments on commit 4a78fc1

Please sign in to comment.