Skip to content

Commit 9418f11

Browse files
committed
OSX testing
1 parent 7846a39 commit 9418f11

2 files changed

Lines changed: 390 additions & 3 deletions

File tree

src/libponyc/codegen/gencshim.cc

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,21 @@
4040
#endif
4141

4242
#include <stdio.h>
43+
#include <stdlib.h>
4344
#include <string.h>
4445
#include <string>
4546
#include <vector>
4647
#include <sys/stat.h>
4748

49+
/*
50+
Compile-time default include headers for Nix enter here and are
51+
interned into the executable so we don't need to wrap ponyc
52+
or require the end user to specify them.
53+
*/
54+
#ifndef PONY_NIX_INCLUDE_DIRS
55+
# define PONY_NIX_INCLUDE_DIRS ""
56+
#endif
57+
4858
#ifdef PLATFORM_IS_WINDOWS
4959
# define PATH_SLASH '\\'
5060
#else
@@ -349,6 +359,148 @@ static bool push_isystem(pass_opt_t* opt, std::vector<const char*>& args,
349359
}
350360

351361

362+
/*
363+
Add each existing directory in a ':' deliminited list as an
364+
-internal-isystem search directory.
365+
*/
366+
static bool add_colon_include_dirs(pass_opt_t* opt, const char* list,
367+
std::vector<const char*>& args, errors_t* errors)
368+
{
369+
if(list == NULL || list[0] == '\0')
370+
return false;
371+
372+
bool any = false;
373+
char buf[FILENAME_MAX];
374+
size_t len = 0;
375+
for(const char* p = list; ; p++)
376+
{
377+
if(*p == ':' || *p == '\0')
378+
{
379+
if(len > 0)
380+
{
381+
buf[len] = '\0';
382+
any |= push_isystem(opt, args, errors, "-internal-isystem", buf, "");
383+
len = 0;
384+
}
385+
if(*p == '\0')
386+
break;
387+
}
388+
else if(len < sizeof(buf) - 1)
389+
{
390+
buf[len++] = *p;
391+
}
392+
}
393+
394+
return any;
395+
}
396+
397+
/*
398+
Unwrap the provided include directories from the nix environment.
399+
As well as covering the basics, this should also include any
400+
includes that would have come via pkgconf et al.
401+
*/
402+
static bool add_flag_string_include_dirs(pass_opt_t* opt, const char* flags,
403+
std::vector<const char*>& args, errors_t* errors)
404+
{
405+
if(flags == NULL || flags[0] == '\0')
406+
return false;
407+
408+
// Tokenize on whitespace first, then interpret include-dir flags.
409+
std::vector<const char*> toks;
410+
char buf[FILENAME_MAX];
411+
size_t len = 0;
412+
for(const char* p = flags; ; p++)
413+
{
414+
if(*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == '\0')
415+
{
416+
if(len > 0)
417+
{
418+
buf[len] = '\0';
419+
toks.push_back(stringtab(opt->strtab, buf));
420+
len = 0;
421+
}
422+
if(*p == '\0')
423+
break;
424+
}
425+
else if(len < sizeof(buf) - 1)
426+
{
427+
buf[len++] = *p;
428+
}
429+
}
430+
431+
bool any = false;
432+
for(size_t i = 0; i < toks.size(); i++)
433+
{
434+
const char* t = toks[i];
435+
const char* dir = NULL;
436+
437+
if(strcmp(t, "-isystem") == 0 || strcmp(t, "-idirafter") == 0 ||
438+
strcmp(t, "-iquote") == 0 || strcmp(t, "-I") == 0)
439+
{
440+
if(i + 1 < toks.size())
441+
dir = toks[++i];
442+
}
443+
else if(strncmp(t, "-I", 2) == 0 && t[2] != '\0')
444+
{
445+
dir = t + 2;
446+
}
447+
448+
if(dir != NULL)
449+
any |= push_isystem(opt, args, errors, "-internal-isystem", dir, "");
450+
}
451+
452+
return any;
453+
}
454+
455+
static bool read_nix_support_file(const char* nix_cc, const char* name,
456+
char* out, size_t outsz)
457+
{
458+
char path[FILENAME_MAX];
459+
snprintf(path, sizeof(path), "%s/nix-support/%s", nix_cc, name);
460+
461+
FILE* f = fopen(path, "rb");
462+
if(f == NULL)
463+
return false;
464+
465+
size_t n = fread(out, 1, outsz - 1, f);
466+
fclose(f);
467+
out[n] = '\0';
468+
469+
while(n > 0 && (out[n - 1] == '\n' || out[n - 1] == '\r' ||
470+
out[n - 1] == ' ' || out[n - 1] == '\t'))
471+
out[--n] = '\0';
472+
473+
return n > 0;
474+
}
475+
476+
/*
477+
Extra include files from the nix environment:
478+
* PONY_NIX_INCLUDE_DIRS
479+
* PONY_INCLUDE_DIRS
480+
* NIX_CFLAGS_COMPILE
481+
*/
482+
static bool add_nix_include_dirs(pass_opt_t* opt,
483+
std::vector<const char*>& args, errors_t* errors)
484+
{
485+
bool any = false;
486+
487+
any |= add_colon_include_dirs(opt, PONY_NIX_INCLUDE_DIRS, args, errors);
488+
any |= add_colon_include_dirs(opt, getenv("PONY_INCLUDE_DIRS"), args, errors);
489+
any |= add_flag_string_include_dirs(opt, getenv("NIX_CFLAGS_COMPILE"), args,
490+
errors);
491+
492+
const char* nix_cc = getenv("NIX_CC");
493+
if(nix_cc != NULL && nix_cc[0] != '\0')
494+
{
495+
char cflags[FILENAME_MAX * 4];
496+
if(read_nix_support_file(nix_cc, "libc-cflags", cflags, sizeof(cflags)))
497+
any |= add_flag_string_include_dirs(opt, cflags, args, errors);
498+
}
499+
500+
return any;
501+
}
502+
503+
352504
// System include directories for the target, derived from the same sysroot
353505
// the embedded linker uses — hand-rolled like LLD rather than driven through
354506
// clang's Driver, so the headers the shim compiles against stay consistent
@@ -488,6 +640,9 @@ static bool add_system_include_args(pass_opt_t* opt, const char* sysroot,
488640
any |= push_isystem(opt, args, errors, "-internal-externc-isystem",
489641
sysroot, "/usr/include");
490642

643+
if(sysroot[0] == '\0')
644+
any |= add_nix_include_dirs(opt, args, errors);
645+
491646
// Per-directory skipping is right (multiarch and /usr/local are
492647
// legitimately absent on many systems), but an explicit --sysroot that
493648
// yields nothing at all deserves a direct answer, like the macOS branch

0 commit comments

Comments
 (0)