You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2014/12/04 22:03:55 UTC

[1/5] lucy-clownfish git commit: Store global error variables in a single struct

Repository: lucy-clownfish
Updated Branches:
  refs/heads/thread_safe_errors [created] 78f6a18a2


Store global error variables in a single struct


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/98282c90
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/98282c90
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/98282c90

Branch: refs/heads/thread_safe_errors
Commit: 98282c907a2d7224363883a8ac7917e6ed81d506
Parents: 55d99f5
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Thu Dec 4 19:34:07 2014 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Dec 4 21:56:18 2014 +0100

----------------------------------------------------------------------
 runtime/c/src/Clownfish/Err.c | 45 +++++++++++++++++++++++++-------------
 1 file changed, 30 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/98282c90/runtime/c/src/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Err.c b/runtime/c/src/Clownfish/Err.c
index eac107f..d08b16f 100644
--- a/runtime/c/src/Clownfish/Err.c
+++ b/runtime/c/src/Clownfish/Err.c
@@ -28,10 +28,19 @@
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/Class.h"
 
+typedef struct {
+    Err *current_error;
+    Err *thrown_error;
+    jmp_buf *current_env;
+} cfish_ErrGlobals;
+
 /* TODO: Thread safety */
-static Err *current_error;
-static Err *thrown_error;
-static jmp_buf  *current_env;
+static cfish_ErrGlobals err_globals;
+
+static cfish_ErrGlobals*
+S_get_globals() {
+    return &err_globals;
+}
 
 void
 Err_init_class(void) {
@@ -39,22 +48,26 @@ Err_init_class(void) {
 
 Err*
 Err_get_error() {
-    return current_error;
+    return S_get_globals()->current_error;
 }
 
 void
 Err_set_error(Err *error) {
-    if (current_error) {
-        DECREF(current_error);
+    cfish_ErrGlobals *globals = S_get_globals();
+
+    if (globals->current_error) {
+        DECREF(globals->current_error);
     }
-    current_error = error;
+    globals->current_error = error;
 }
 
 void
 Err_do_throw(Err *error) {
-    if (current_env) {
-        thrown_error = error;
-        longjmp(*current_env, 1);
+    cfish_ErrGlobals *globals = S_get_globals();
+
+    if (globals->current_env) {
+        globals->thrown_error = error;
+        longjmp(*globals->current_env, 1);
     }
     else {
         String *message = Err_Get_Mess(error);
@@ -89,18 +102,20 @@ Err_warn_mess(String *message) {
 
 Err*
 Err_trap(Err_Attempt_t routine, void *context) {
+    cfish_ErrGlobals *globals = S_get_globals();
+
     jmp_buf  env;
-    jmp_buf *prev_env = current_env;
-    current_env = &env;
+    jmp_buf *prev_env = globals->current_env;
+    globals->current_env = &env;
 
     if (!setjmp(env)) {
         routine(context);
     }
 
-    current_env = prev_env;
+    globals->current_env = prev_env;
 
-    Err *error = thrown_error;
-    thrown_error = NULL;
+    Err *error = globals->thrown_error;
+    globals->thrown_error = NULL;
     return error;
 }
 


[4/5] lucy-clownfish git commit: Add probe for libpthread

Posted by nw...@apache.org.
Add probe for libpthread


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/f1f316ed
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/f1f316ed
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/f1f316ed

Branch: refs/heads/thread_safe_errors
Commit: f1f316ed6717af8e5847f4b3f2747bd4a8e2517e
Parents: 8b939e5
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Thu Dec 4 21:54:03 2014 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Dec 4 21:56:18 2014 +0100

----------------------------------------------------------------------
 runtime/common/charmonizer.main | 41 ++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f1f316ed/runtime/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.main b/runtime/common/charmonizer.main
index 30bdff2..207599a 100644
--- a/runtime/common/charmonizer.main
+++ b/runtime/common/charmonizer.main
@@ -93,6 +93,9 @@ S_cfh_file_callback(const char *dir, char *file, void *context);
 static int
 S_ends_with(const char *string, const char *postfix);
 
+static int
+S_need_libpthread(chaz_CLI *cli);
+
 int main(int argc, const char **argv) {
     /* Initialize. */
     chaz_CLI *cli
@@ -377,6 +380,9 @@ cfish_MakeFile_write(cfish_MakeFile *self) {
     if (math_library) {
         chaz_CFlags_add_external_library(link_flags, math_library);
     }
+    if (S_need_libpthread(self->cli)) {
+        chaz_CFlags_add_external_library(link_flags, "pthread");
+    }
     if (chaz_CLI_defined(self->cli, "enable-coverage")) {
         chaz_CFlags_enable_code_coverage(link_flags);
     }
@@ -552,4 +558,39 @@ S_ends_with(const char *string, const char *postfix) {
            && memcmp(string + len - postfix_len, postfix, postfix_len) == 0;
 }
 
+static int
+S_need_libpthread(chaz_CLI *cli) {
+    if (chaz_CLI_defined(cli, "disable-threads")
+        || strcmp(chaz_CLI_strval(cli, "host"), "c") != 0
+        || chaz_HeadCheck_check_header("windows.h")
+    ) {
+        return 0;
+    }
+
+    if (!chaz_HeadCheck_check_header("pthread.h")) {
+        chaz_Util_die("pthread.h not found. Try --disable-threads.");
+    }
+
+    static const char source[] =
+        "#include <pthread.h>\n"
+        "\n"
+        "int main() {\n"
+        "    pthread_key_t key;\n"
+        "    pthread_key_create(&key, NULL);\n"
+        "    return 0;\n"
+        "}\n";
+
+    if (chaz_CC_test_link(source)) {
+        return 0;
+    }
+
+    chaz_CFlags *temp_cflags = chaz_CC_get_temp_cflags();
+    chaz_CFlags_add_external_library(temp_cflags, "pthread");
+    if (!chaz_CC_test_link(source)) {
+        chaz_Util_die("Can't link with libpthread. Try --disable-threads.");
+    }
+    chaz_CFlags_clear(temp_cflags);
+
+    return 1;
+}
 


[5/5] lucy-clownfish git commit: Use thread-local storage in Err.c

Posted by nw...@apache.org.
Use thread-local storage in Err.c

Fixes CLOWNFISH-24. Untested on Windows.


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/78f6a18a
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/78f6a18a
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/78f6a18a

Branch: refs/heads/thread_safe_errors
Commit: 78f6a18a2952df7d8f733c2ed4ca508f60c1e5de
Parents: 98282c9
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Thu Dec 4 20:41:02 2014 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Dec 4 22:02:50 2014 +0100

----------------------------------------------------------------------
 runtime/c/src/Clownfish/Err.c | 96 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 94 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/78f6a18a/runtime/c/src/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Err.c b/runtime/c/src/Clownfish/Err.c
index d08b16f..a6e5090 100644
--- a/runtime/c/src/Clownfish/Err.c
+++ b/runtime/c/src/Clownfish/Err.c
@@ -34,18 +34,110 @@ typedef struct {
     jmp_buf *current_env;
 } cfish_ErrGlobals;
 
-/* TODO: Thread safety */
+/**************************** No thread support ****************************/
+#ifdef CFISH_NOTHREADS
+
 static cfish_ErrGlobals err_globals;
 
+void
+Err_init_class() {
+}
+
 static cfish_ErrGlobals*
 S_get_globals() {
     return &err_globals;
 }
 
+/********************************** Windows ********************************/
+#elif defined(CHY_HAS_WINDOWS_H)
+
+#include <windows.h>
+
+static DWORD err_globals_tls_index;
+
 void
-Err_init_class(void) {
+Err_init_class() {
+    err_globals_tls_index = TlsAlloc();
+    if (err_globals_tls_index == TLS_OUT_OF_INDEXES) {
+        fprintf(stderr, "TlsAlloc failed (TLS_OUT_OF_INDEXES)\n");
+        abort();
+    }
 }
 
+static cfish_ErrGlobals*
+S_get_globals() {
+    cfish_ErrGlobals *globals
+        = (cfish_ErrGlobals*)TlsGetValue(err_globals_tls_index);
+
+    if (!globals) {
+        globals = (cfish_ErrGlobals*)MALLOCATE(sizeof(cfish_ErrGlobals));
+        if (!TlsSetValue(err_globals_tls_index, globals)) {
+            fprintf(stderr, "TlsSetValue failed: %d\n", GetLastError());
+            abort();
+        }
+    }
+
+    return globals;
+}
+
+BOOL WINAPI
+DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved) {
+    if (reason == DLL_THREAD_DETACH) {
+        void *globals = TlsGetValue(err_globals_tls_index);
+        FREEMEM(globals);
+    }
+
+    return TRUE;
+}
+
+/******************************** pthreads *********************************/
+#elif defined(CHY_HAS_PTHREAD_H)
+
+#include <pthread.h>
+
+static pthread_key_t err_globals_key;
+
+static void
+S_destroy_globals(void *globals);
+
+void
+Err_init_class() {
+    int error = pthread_key_create(&err_globals_key, S_destroy_globals);
+    if (error) {
+        fprintf(stderr, "pthread_key_create failed: %d\n", error);
+        abort();
+    }
+}
+
+static cfish_ErrGlobals*
+S_get_globals() {
+    cfish_ErrGlobals *globals
+        = (cfish_ErrGlobals*)pthread_getspecific(err_globals_key);
+
+    if (!globals) {
+        globals = (cfish_ErrGlobals*)MALLOCATE(sizeof(cfish_ErrGlobals));
+        int error = pthread_setspecific(err_globals_key, globals);
+        if (error) {
+            fprintf(stderr, "pthread_setspecific failed: %d\n", error);
+            abort();
+        }
+    }
+
+    return globals;
+}
+
+static void
+S_destroy_globals(void *globals) {
+    FREEMEM(globals);
+}
+
+/****************** No support for thread-local storage ********************/
+#else
+
+#error "No support for thread-local storage."
+
+#endif
+
 Err*
 Err_get_error() {
     return S_get_globals()->current_error;


[3/5] lucy-clownfish git commit: Add "host" CLI arg for Clownfish runtime

Posted by nw...@apache.org.
Add "host" CLI arg for Clownfish runtime


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/8b939e59
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/8b939e59
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/8b939e59

Branch: refs/heads/thread_safe_errors
Commit: 8b939e5957789013899306ae11ac1b6bd7f4d1cb
Parents: c3aadd5
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Thu Dec 4 20:55:27 2014 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Dec 4 21:56:18 2014 +0100

----------------------------------------------------------------------
 compiler/perl/lib/Clownfish/CFC/Perl/Build/Charmonic.pm |  1 +
 runtime/c/configure                                     |  2 +-
 runtime/c/configure.bat                                 |  2 +-
 runtime/common/charmonizer.main                         | 10 ++++++----
 4 files changed, 9 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8b939e59/compiler/perl/lib/Clownfish/CFC/Perl/Build/Charmonic.pm
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC/Perl/Build/Charmonic.pm b/compiler/perl/lib/Clownfish/CFC/Perl/Build/Charmonic.pm
index a37b6b4..7d55bb4 100644
--- a/compiler/perl/lib/Clownfish/CFC/Perl/Build/Charmonic.pm
+++ b/compiler/perl/lib/Clownfish/CFC/Perl/Build/Charmonic.pm
@@ -79,6 +79,7 @@ sub ACTION_charmony {
     my @command = (
         $CHARMONIZER_EXE_PATH,
         "--cc=$cc",
+        '--host=perl',
         '--enable-c',
         '--enable-perl',
     );

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8b939e59/runtime/c/configure
----------------------------------------------------------------------
diff --git a/runtime/c/configure b/runtime/c/configure
index 29b0c14..9557e66 100755
--- a/runtime/c/configure
+++ b/runtime/c/configure
@@ -48,5 +48,5 @@ echo $command
 $command || exit
 
 echo Running charmonizer
-./charmonizer --cc="$CC" --enable-c --enable-makefile "$@"
+./charmonizer --cc="$CC" --host=c --enable-c --enable-makefile "$@"
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8b939e59/runtime/c/configure.bat
----------------------------------------------------------------------
diff --git a/runtime/c/configure.bat b/runtime/c/configure.bat
index 40b5cb0..9a34abd 100644
--- a/runtime/c/configure.bat
+++ b/runtime/c/configure.bat
@@ -40,7 +40,7 @@ echo cl /nologo ..\common\charmonizer.c
 cl /nologo ..\common\charmonizer.c
 if errorlevel 1 exit /b 1
 echo Running charmonizer
-charmonizer.exe --cc=cl --enable-c --enable-makefile %*
+charmonizer.exe --cc=cl --host=c --enable-c --enable-makefile %*
 exit /b
 
 :found_gcc

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8b939e59/runtime/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.main b/runtime/common/charmonizer.main
index 4c2bcd5..30bdff2 100644
--- a/runtime/common/charmonizer.main
+++ b/runtime/common/charmonizer.main
@@ -97,6 +97,8 @@ int main(int argc, const char **argv) {
     /* Initialize. */
     chaz_CLI *cli
         = chaz_CLI_new(argv[0], "charmonizer: Probe C build environment");
+    chaz_CLI_register(cli, "host", "specify host binding language",
+                      CHAZ_CLI_ARG_REQUIRED);
     chaz_CLI_register(cli, "disable-threads", "whether to disable threads",
                       CHAZ_CLI_NO_ARG);
     chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]");
@@ -185,7 +187,7 @@ S_add_compiler_flags(struct chaz_CLI *cli) {
         else if (getenv("LUCY_DEBUG")) {
             chaz_CFlags_append(extra_cflags,
                 "-DLUCY_DEBUG -pedantic -Wall -Wextra -Wno-variadic-macros");
-            if (chaz_CLI_defined(cli, "enable-perl")) {
+            if (strcmp(chaz_CLI_strval(cli, "host"), "perl") == 0) {
                 chaz_CFlags_append(extra_cflags, "-DPERL_GCC_PEDANTIC");
             }
         }
@@ -235,7 +237,7 @@ cfish_MakeFile_new(chaz_CLI *cli) {
     self->autogen_target
         = chaz_Util_join(dir_sep, "autogen", "hierarchy.json", NULL);
 
-    if (chaz_CLI_defined(cli, "enable-perl")) {
+    if (strcmp(chaz_CLI_strval(self->cli, "host"), "perl") == 0) {
         static const char *perl_autogen_src_files[] = {
             "boot",
             "callbacks",
@@ -355,7 +357,7 @@ cfish_MakeFile_write(cfish_MakeFile *self) {
     chaz_MakeFile_add_rule(self->makefile, "all", scratch);
     free(scratch);
 
-    if (!chaz_CLI_defined(self->cli, "enable-perl")) {
+    if (strcmp(chaz_CLI_strval(self->cli, "host"), "c") == 0) {
         cfish_MakeFile_write_c_cfc_rules(self);
     }
 
@@ -384,7 +386,7 @@ cfish_MakeFile_write(cfish_MakeFile *self) {
     chaz_MakeFile_add_static_lib(self->makefile, self->static_lib,
                                  "$(CLOWNFISH_OBJS)");
 
-    if (!chaz_CLI_defined(self->cli, "enable-perl")) {
+    if (strcmp(chaz_CLI_strval(self->cli, "host"), "c") == 0) {
         cfish_MakeFile_write_c_test_rules(self);
     }
 


[2/5] lucy-clownfish git commit: Regenerate charmonizer.c

Posted by nw...@apache.org.
Regenerate charmonizer.c


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/55d99f5e
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/55d99f5e
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/55d99f5e

Branch: refs/heads/thread_safe_errors
Commit: 55d99f5e2b0ee1b8ec25a7c0d6925eee524f9f65
Parents: f1f316e
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Thu Dec 4 21:54:58 2014 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Thu Dec 4 21:56:18 2014 +0100

----------------------------------------------------------------------
 compiler/common/charmonizer.c | 18 ++++++++++
 runtime/common/charmonizer.c  | 69 +++++++++++++++++++++++++++++++++++---
 2 files changed, 83 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/55d99f5e/compiler/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/compiler/common/charmonizer.c b/compiler/common/charmonizer.c
index 2a24d21..0d295c2 100644
--- a/compiler/common/charmonizer.c
+++ b/compiler/common/charmonizer.c
@@ -301,6 +301,12 @@ chaz_CC_compile_obj(const char *source_path, const char *obj_path,
 int
 chaz_CC_test_compile(const char *source);
 
+/* Attempt to compile and link the supplied source code and return true if
+ * the effort succeeds.
+ */
+int
+chaz_CC_test_link(const char *source);
+
 /* Attempt to compile the supplied source code.  If successful, capture the
  * output of the program and return a pointer to a newly allocated buffer.
  * If the compilation fails, return NULL.  The length of the captured
@@ -2793,6 +2799,18 @@ chaz_CC_test_compile(const char *source) {
     return compile_succeeded;
 }
 
+int
+chaz_CC_test_link(const char *source) {
+    int link_succeeded;
+    if (!chaz_Util_remove_and_verify(chaz_CC.try_exe_name)) {
+        chaz_Util_die("Failed to delete file '%s'", chaz_CC.try_exe_name);
+    }
+    link_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH,
+                                         CHAZ_CC_TRY_BASENAME, source);
+    chaz_Util_remove_and_verify(chaz_CC.try_exe_name);
+    return link_succeeded;
+}
+
 char*
 chaz_CC_capture_output(const char *source, size_t *output_len) {
     char *captured_output = NULL;

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/55d99f5e/runtime/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.c b/runtime/common/charmonizer.c
index 133494b..1d0fe07 100644
--- a/runtime/common/charmonizer.c
+++ b/runtime/common/charmonizer.c
@@ -301,6 +301,12 @@ chaz_CC_compile_obj(const char *source_path, const char *obj_path,
 int
 chaz_CC_test_compile(const char *source);
 
+/* Attempt to compile and link the supplied source code and return true if
+ * the effort succeeds.
+ */
+int
+chaz_CC_test_link(const char *source);
+
 /* Attempt to compile the supplied source code.  If successful, capture the
  * output of the program and return a pointer to a newly allocated buffer.
  * If the compilation fails, return NULL.  The length of the captured
@@ -2793,6 +2799,18 @@ chaz_CC_test_compile(const char *source) {
     return compile_succeeded;
 }
 
+int
+chaz_CC_test_link(const char *source) {
+    int link_succeeded;
+    if (!chaz_Util_remove_and_verify(chaz_CC.try_exe_name)) {
+        chaz_Util_die("Failed to delete file '%s'", chaz_CC.try_exe_name);
+    }
+    link_succeeded = chaz_CC_compile_exe(CHAZ_CC_TRY_SOURCE_PATH,
+                                         CHAZ_CC_TRY_BASENAME, source);
+    chaz_Util_remove_and_verify(chaz_CC.try_exe_name);
+    return link_succeeded;
+}
+
 char*
 chaz_CC_capture_output(const char *source, size_t *output_len) {
     char *captured_output = NULL;
@@ -7773,10 +7791,15 @@ S_cfh_file_callback(const char *dir, char *file, void *context);
 static int
 S_ends_with(const char *string, const char *postfix);
 
+static int
+S_need_libpthread(chaz_CLI *cli);
+
 int main(int argc, const char **argv) {
     /* Initialize. */
     chaz_CLI *cli
         = chaz_CLI_new(argv[0], "charmonizer: Probe C build environment");
+    chaz_CLI_register(cli, "host", "specify host binding language",
+                      CHAZ_CLI_ARG_REQUIRED);
     chaz_CLI_register(cli, "disable-threads", "whether to disable threads",
                       CHAZ_CLI_NO_ARG);
     chaz_CLI_set_usage(cli, "Usage: charmonizer [OPTIONS] [-- [CFLAGS]]");
@@ -7865,7 +7888,7 @@ S_add_compiler_flags(struct chaz_CLI *cli) {
         else if (getenv("LUCY_DEBUG")) {
             chaz_CFlags_append(extra_cflags,
                 "-DLUCY_DEBUG -pedantic -Wall -Wextra -Wno-variadic-macros");
-            if (chaz_CLI_defined(cli, "enable-perl")) {
+            if (strcmp(chaz_CLI_strval(cli, "host"), "perl") == 0) {
                 chaz_CFlags_append(extra_cflags, "-DPERL_GCC_PEDANTIC");
             }
         }
@@ -7915,7 +7938,7 @@ cfish_MakeFile_new(chaz_CLI *cli) {
     self->autogen_target
         = chaz_Util_join(dir_sep, "autogen", "hierarchy.json", NULL);
 
-    if (chaz_CLI_defined(cli, "enable-perl")) {
+    if (strcmp(chaz_CLI_strval(self->cli, "host"), "perl") == 0) {
         static const char *perl_autogen_src_files[] = {
             "boot",
             "callbacks",
@@ -8035,7 +8058,7 @@ cfish_MakeFile_write(cfish_MakeFile *self) {
     chaz_MakeFile_add_rule(self->makefile, "all", scratch);
     free(scratch);
 
-    if (!chaz_CLI_defined(self->cli, "enable-perl")) {
+    if (strcmp(chaz_CLI_strval(self->cli, "host"), "c") == 0) {
         cfish_MakeFile_write_c_cfc_rules(self);
     }
 
@@ -8055,6 +8078,9 @@ cfish_MakeFile_write(cfish_MakeFile *self) {
     if (math_library) {
         chaz_CFlags_add_external_library(link_flags, math_library);
     }
+    if (S_need_libpthread(self->cli)) {
+        chaz_CFlags_add_external_library(link_flags, "pthread");
+    }
     if (chaz_CLI_defined(self->cli, "enable-coverage")) {
         chaz_CFlags_enable_code_coverage(link_flags);
     }
@@ -8064,7 +8090,7 @@ cfish_MakeFile_write(cfish_MakeFile *self) {
     chaz_MakeFile_add_static_lib(self->makefile, self->static_lib,
                                  "$(CLOWNFISH_OBJS)");
 
-    if (!chaz_CLI_defined(self->cli, "enable-perl")) {
+    if (strcmp(chaz_CLI_strval(self->cli, "host"), "c") == 0) {
         cfish_MakeFile_write_c_test_rules(self);
     }
 
@@ -8230,4 +8256,39 @@ S_ends_with(const char *string, const char *postfix) {
            && memcmp(string + len - postfix_len, postfix, postfix_len) == 0;
 }
 
+static int
+S_need_libpthread(chaz_CLI *cli) {
+    if (chaz_CLI_defined(cli, "disable-threads")
+        || strcmp(chaz_CLI_strval(cli, "host"), "c") != 0
+        || chaz_HeadCheck_check_header("windows.h")
+    ) {
+        return 0;
+    }
+
+    if (!chaz_HeadCheck_check_header("pthread.h")) {
+        chaz_Util_die("pthread.h not found. Try --disable-threads.");
+    }
+
+    static const char source[] =
+        "#include <pthread.h>\n"
+        "\n"
+        "int main() {\n"
+        "    pthread_key_t key;\n"
+        "    pthread_key_create(&key, NULL);\n"
+        "    return 0;\n"
+        "}\n";
+
+    if (chaz_CC_test_link(source)) {
+        return 0;
+    }
+
+    chaz_CFlags *temp_cflags = chaz_CC_get_temp_cflags();
+    chaz_CFlags_add_external_library(temp_cflags, "pthread");
+    if (!chaz_CC_test_link(source)) {
+        chaz_Util_die("Can't link with libpthread. Try --disable-threads.");
+    }
+    chaz_CFlags_clear(temp_cflags);
+
+    return 1;
+}