Repository: lucy-clownfish
Updated Branches:
  refs/heads/master f8dd6b938 -> bb48393df


Perl build with make

Let Charmonizer create a Makefile for the Perl bindings that builds the
core object files. The list of object files is passed in a Charmonizer
variable named `CORE_OBJECTS`.

Make options can be passed by running

    perl Build.PL --charmonizer_params make_options=<options>

Module::Build options can also be specified in ~/.modulebuildrc, so an
easy way to always launch parallel builds is to add a line like

    Build_PL --charmonizer_params make_options=-j5


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

Branch: refs/heads/master
Commit: e169fbe3bdb946dcec42d920af916ef49e91068e
Parents: c7be35b
Author: Nick Wellnhofer <[email protected]>
Authored: Sat Jun 4 20:04:14 2016 +0200
Committer: Nick Wellnhofer <[email protected]>
Committed: Sat Jun 4 20:21:47 2016 +0200

----------------------------------------------------------------------
 compiler/perl/lib/Clownfish/CFC/Perl/Build.pm   |  14 ++-
 .../lib/Clownfish/CFC/Perl/Build/Charmonic.pm   |  58 ++++++++--
 runtime/common/charmonizer.c                    | 115 ++++++++++---------
 runtime/common/charmonizer.main                 | 115 ++++++++++---------
 runtime/perl/.gitignore                         |   1 +
 runtime/perl/buildlib/Clownfish/Build.pm        |   4 +-
 6 files changed, 184 insertions(+), 123 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e169fbe3/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm 
b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
index 8e7689b..7c522e7 100644
--- a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
+++ b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
@@ -368,13 +368,21 @@ sub ACTION_compile_custom_xs {
     mkpath( $archdir, 0, 0777 ) unless -d $archdir;
     my @objects;
 
+    # Make core objects.
+    if ($self->can('cf_make_core_objects')) {
+        my $core_objects = $self->cf_make_core_objects();
+        push @objects, @$core_objects;
+        $self->add_to_cleanup(@$core_objects);
+    }
+
     # Compile C source files.
     my $c_files = [];
-    my $source_dirs = $self->clownfish_params('source');
-    my $autogen_src_dir = catdir( $AUTOGEN_DIR, 'source' );
-    for my $source_dir ( @$source_dirs, $autogen_src_dir ) {
+    my $source_dirs = $self->clownfish_params('c_source');
+    for my $source_dir (@$source_dirs) {
         push @$c_files, @{ $self->rscan_dir( $source_dir, qr/\.c$/ ) };
     }
+    my $autogen_src_dir = catdir( $AUTOGEN_DIR, 'source' );
+    push @$c_files, @{ $self->rscan_dir( $autogen_src_dir, qr/_perl\.c$/ ) };
     my $extra_cflags = $self->clownfish_params('cflags');
     for my $c_file (@$c_files) {
         my $o_file   = $c_file;

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e169fbe3/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 045d98a..03b48f5 100644
--- a/compiler/perl/lib/Clownfish/CFC/Perl/Build/Charmonic.pm
+++ b/compiler/perl/lib/Clownfish/CFC/Perl/Build/Charmonic.pm
@@ -31,6 +31,8 @@ use File::Spec::Functions qw( catfile curdir );
 # Add a custom Module::Build hashref property to pass the following build
 # parameters.
 # charmonizer_c: Charmonizer C file, required
+# create_makefile: Whether to create a Makefile.
+# make_options: Options passed to make.
 if ( $Module::Build::VERSION <= 0.30 ) {
     __PACKAGE__->add_property( charmonizer_params => {} );
 }
@@ -49,19 +51,29 @@ my $CHARMONY_PM_PATH     = 'Charmony.pm';
 # Charmony.pm files.
 sub ACTION_charmony {
     my $self = shift;
-    my $charmonizer_c = $self->charmonizer_params('charmonizer_c');
+
+    my ($cc, @cc_args)  = $self->split_like_shell($self->config('cc'));
+    my $is_msvc         = lc($cc) =~ /^cl\b/;
+    my $charmonizer_c   = $self->charmonizer_params('charmonizer_c');
+    my $create_makefile = $self->charmonizer_params('create_makefile');
+
     $self->add_to_cleanup($CHARMONIZER_EXE_PATH);
     if ( !$self->up_to_date( $charmonizer_c, $CHARMONIZER_EXE_PATH ) ) {
         print "\nCompiling $CHARMONIZER_EXE_PATH...\n\n";
-        my $cc = $self->config('cc');
-        my $outflag = $cc =~ /cl\b/ ? "/Fe" : "-o ";
-        system("$cc $charmonizer_c $outflag$CHARMONIZER_EXE_PATH")
+        my @command = ($cc, @cc_args, $charmonizer_c);
+        if ($is_msvc) {
+            push @command, "/Fe$CHARMONIZER_EXE_PATH";
+        }
+        else {
+            push @command, '-o', $CHARMONIZER_EXE_PATH;
+        }
+        system @command
             and die "Failed to compile $CHARMONIZER_EXE_PATH";
     }
 
-    return if $self->up_to_date( $CHARMONIZER_EXE_PATH, [
-        $CHARMONY_H_PATH, $CHARMONY_PM_PATH,
-    ] );
+    my @derived_files = ( $CHARMONY_H_PATH, $CHARMONY_PM_PATH );
+    push @derived_files, 'Makefile' if $create_makefile;
+    return if $self->up_to_date( $CHARMONIZER_EXE_PATH, \@derived_files );
     print "\nRunning $CHARMONIZER_EXE_PATH...\n\n";
 
     $self->add_to_cleanup($CHARMONY_H_PATH);
@@ -69,13 +81,11 @@ sub ACTION_charmony {
     # Clean up after charmonizer if it doesn't succeed on its own.
     $self->add_to_cleanup("_charm*");
 
-    if ($Config{cc} =~ /^cl\b/) {
+    if ($is_msvc) {
         $self->add_to_cleanup('charmonizer.obj');
     }
 
     # Prepare arguments to charmonizer.
-    my @cc_args = $self->split_like_shell($self->config('cc'));
-    my $cc = shift(@cc_args);
     my @command = (
         $CHARMONIZER_EXE_PATH,
         "--cc=$cc",
@@ -83,10 +93,19 @@ sub ACTION_charmony {
         '--enable-c',
         '--enable-perl',
     );
+    if ($create_makefile) {
+        push @command,
+             '--make=' . $self->config('make'),
+             '--enable-makefile';
+        $self->add_to_cleanup('Makefile');
+    }
     if ( !$self->config('usethreads') ) {
         push @command, '--disable-threads';
     }
-    push @command, ( '--', @cc_args, $self->config('ccflags') );
+    push @command, (
+        '--', @cc_args, $self->config('ccflags'),
+        '-I' . File::Spec->catdir($self->config('archlibexp'), 'CORE'),
+    );
     if ( $ENV{CHARM_VALGRIND} ) {
         unshift @command, "valgrind", "--leak-check=yes";
     }
@@ -121,6 +140,23 @@ sub charmony {
     return;
 }
 
+sub cf_make_core_objects {
+    my $self = shift;
+
+    return [] unless $self->charmonizer_params('create_makefile');
+
+    my $make_options = $self->charmonizer_params('make_options');
+    my @command = (
+        $self->config('make'),
+        $self->split_like_shell($make_options),
+        'core_objects',
+    );
+    print join(' ', @command), "\n";
+    system @command and die($self->config('make') . " failed");
+
+    return [ split( /\s+/, $self->charmony('CORE_OBJECTS') ) ];
+}
+
 1;
 
 __END__

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e169fbe3/runtime/common/charmonizer.c
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.c b/runtime/common/charmonizer.c
index c6e1e1e..62355e8 100644
--- a/runtime/common/charmonizer.c
+++ b/runtime/common/charmonizer.c
@@ -8323,6 +8323,8 @@ chaz_VariadicMacros_run(void) {
 
 typedef struct cfish_MakeFile {
     chaz_MakeFile *makefile;
+    chaz_MakeVar  *obj_var;
+    chaz_MakeVar  *cfh_var;
     chaz_CLI      *cli;
 
     /* Directories and files. */
@@ -8332,7 +8334,7 @@ typedef struct cfish_MakeFile {
     char        *autogen_src_dir;
     char        *autogen_inc_dir;
     char        *autogen_target;
-    const char **autogen_src_files;
+    char        *core_objects;
 
     /* Libraries. */
     chaz_Lib *shared_lib;
@@ -8341,10 +8343,6 @@ typedef struct cfish_MakeFile {
     char     *static_lib_filename;
 } cfish_MakeFile;
 
-typedef struct SourceFileContext {
-    chaz_MakeVar *var;
-} SourceFileContext;
-
 static const char cfish_version[]       = "0.5.0";
 static const char cfish_major_version[] = "0.5";
 
@@ -8373,6 +8371,9 @@ static void
 S_c_file_callback(const char *dir, char *file, void *context);
 
 static void
+S_add_core_object(cfish_MakeFile *self, const char *obj_file);
+
+static void
 S_cfh_file_callback(const char *dir, char *file, void *context);
 
 static int
@@ -8468,6 +8469,7 @@ int main(int argc, const char **argv) {
                                 mf->shared_lib_filename);
         chaz_ConfWriter_add_def("STATIC_LIB_FILENAME",
                                 mf->static_lib_filename);
+        chaz_ConfWriter_add_def("CORE_OBJECTS", mf->core_objects);
         cfish_MakeFile_destroy(mf);
     }
 
@@ -8552,6 +8554,9 @@ cfish_MakeFile_new(chaz_CLI *cli) {
     cfish_MakeFile *self = malloc(sizeof(cfish_MakeFile));
 
     self->makefile = chaz_MakeFile_new();
+    self->obj_var  = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_OBJS",
+                                           NULL);
+    self->cfh_var  = NULL;
     self->cli      = cli;
 
     self->base_dir = "..";
@@ -8563,42 +8568,18 @@ cfish_MakeFile_new(chaz_CLI *cli) {
         = chaz_Util_join(dir_sep, "autogen", "hierarchy.json", NULL);
 
     if (strcmp(chaz_CLI_strval(cli, "host"), "go") == 0) {
-        static const char *go_autogen_src_files[] = {
-            "cfish_parcel",
-            "testcfish_parcel",
-            NULL
-        };
+        /* TODO: Let Go bindings build code in "ext". */
         self->host_src_dir = "ext";
-        self->autogen_src_files = go_autogen_src_files;
     }
     else if (chaz_CLI_defined(cli, "enable-python")) {
-        static const char *python_autogen_src_files[] = {
-            "cfish_parcel",
-            "testcfish_parcel",
-            NULL
-        };
+        /* TODO: Let Python bindings build code in "cfext". */
         self->host_src_dir = "cfext";
-        self->autogen_src_files = python_autogen_src_files;
-    }
-    else if (chaz_CLI_defined(cli, "enable-perl")) {
-        static const char *perl_autogen_src_files[] = {
-            "cfish_parcel",
-            "cfish_perl",
-            "testcfish_parcel",
-            "testcfish_perl",
-            NULL
-        };
-        self->host_src_dir = "xs";
-        self->autogen_src_files = perl_autogen_src_files;
     }
-    else {
-        static const char *c_autogen_src_files[] = {
-            "cfish_parcel",
-            "testcfish_parcel",
-            NULL
-        };
+    else if (strcmp(chaz_CLI_strval(cli, "host"), "c") == 0) {
         self->host_src_dir = "src";
-        self->autogen_src_files = c_autogen_src_files;
+    }
+    else {
+        self->host_src_dir = NULL;
     }
 
     self->shared_lib = chaz_Lib_new_shared("cfish", cfish_version,
@@ -8606,6 +8587,7 @@ cfish_MakeFile_new(chaz_CLI *cli) {
     self->static_lib = chaz_Lib_new_static("clownfish");
     self->shared_lib_filename = chaz_Lib_filename(self->shared_lib);
     self->static_lib_filename = chaz_Lib_filename(self->static_lib);
+    self->core_objects = chaz_Util_strdup("");
 
     return self;
 }
@@ -8623,13 +8605,18 @@ cfish_MakeFile_destroy(cfish_MakeFile *self) {
     chaz_Lib_destroy(self->static_lib);
     free(self->shared_lib_filename);
     free(self->static_lib_filename);
+    free(self->core_objects);
 
     free(self);
 }
 
 static void
 cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
-    SourceFileContext sfc;
+    static const char *const autogen_src_files[] = {
+        "cfish_parcel",
+        "testcfish_parcel",
+        NULL
+    };
 
     const char *dir_sep  = chaz_OS_dir_sep();
     const char *obj_ext  = chaz_CC_obj_ext();
@@ -8668,7 +8655,9 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags 
*extra_link_flags) {
 
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
     chaz_CFlags_add_include_dir(makefile_cflags, self->core_dir);
-    chaz_CFlags_add_include_dir(makefile_cflags, self->host_src_dir);
+    if (self->host_src_dir) {
+        chaz_CFlags_add_include_dir(makefile_cflags, self->host_src_dir);
+    }
     chaz_CFlags_add_include_dir(makefile_cflags, self->autogen_inc_dir);
 
     var = chaz_MakeFile_add_var(self->makefile, "CFLAGS", NULL);
@@ -8680,15 +8669,15 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags 
*extra_link_flags) {
 
     /* Object files */
 
-    var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_OBJS", NULL);
-    sfc.var = var;
-    chaz_Make_list_files(self->host_src_dir, "c", S_c_file_callback, &sfc);
-    chaz_Make_list_files(self->core_dir,     "c", S_c_file_callback, &sfc);
+    if (self->host_src_dir) {
+        chaz_Make_list_files(self->host_src_dir, "c", S_c_file_callback, self);
+    }
+    chaz_Make_list_files(self->core_dir, "c", S_c_file_callback, self);
 
-    for (i = 0; self->autogen_src_files[i] != NULL; ++i) {
+    for (i = 0; autogen_src_files[i] != NULL; ++i) {
         char *path = chaz_Util_join("", self->autogen_src_dir, dir_sep,
-                                    self->autogen_src_files[i], obj_ext, NULL);
-        chaz_MakeVar_append(var, path);
+                                    autogen_src_files[i], obj_ext, NULL);
+        S_add_core_object(self, path);
         free(path);
     }
 
@@ -8696,15 +8685,17 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags 
*extra_link_flags) {
 
     chaz_MakeFile_add_rule(self->makefile, "all", self->shared_lib_filename);
     chaz_MakeFile_add_rule(self->makefile, "static", 
self->static_lib_filename);
+    chaz_MakeFile_add_rule(self->makefile, "core_objects",
+                           "$(CLOWNFISH_OBJS)");
 
     if (strcmp(chaz_CLI_strval(self->cli, "host"), "c") == 0) {
         cfish_MakeFile_write_c_cfc_rules(self);
     }
 
     /* Needed for parallel builds. */
-    for (i = 0; self->autogen_src_files[i] != NULL; ++i) {
+    for (i = 0; autogen_src_files[i] != NULL; ++i) {
         char *path = chaz_Util_join("", self->autogen_src_dir, dir_sep,
-                                    self->autogen_src_files[i], ".c", NULL);
+                                    autogen_src_files[i], ".c", NULL);
         chaz_MakeFile_add_rule(self->makefile, path, self->autogen_target);
         free(path);
     }
@@ -8734,7 +8725,6 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags 
*extra_link_flags) {
 
 static void
 cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
-    SourceFileContext sfc;
     chaz_MakeVar  *var;
     chaz_MakeRule *rule;
 
@@ -8752,9 +8742,9 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
     rule = chaz_MakeFile_add_rule(self->makefile, cfc_exe, NULL);
     chaz_MakeRule_add_make_command(rule, cfc_dir, NULL);
 
-    var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_HEADERS", NULL);
-    sfc.var = var;
-    chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, &sfc);
+    self->cfh_var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_HEADERS",
+                                          NULL);
+    chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, self);
 
     rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target, 
cfc_exe);
     chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
@@ -8874,7 +8864,7 @@ cfish_MakeFile_write_c_test_rules(cfish_MakeFile *self) {
 
 static void
 S_c_file_callback(const char *dir, char *file, void *context) {
-    SourceFileContext *sfc = (SourceFileContext*)context;
+    cfish_MakeFile *self = (cfish_MakeFile*)context;
     const char *dir_sep = chaz_OS_dir_sep();
     const char *obj_ext = chaz_CC_obj_ext();
     size_t file_len = strlen(file);
@@ -8888,13 +8878,30 @@ S_c_file_callback(const char *dir, char *file, void 
*context) {
     file[file_len-2] = '\0';
 
     obj_file = chaz_Util_join("", dir, dir_sep, file, obj_ext, NULL);
-    chaz_MakeVar_append(sfc->var, obj_file);
+    S_add_core_object(self, obj_file);
     free(obj_file);
 }
 
 static void
+S_add_core_object(cfish_MakeFile *self, const char *obj_file) {
+    char *new_core_objects;
+
+    chaz_MakeVar_append(self->obj_var, obj_file);
+
+    if (self->core_objects[0] == '\0') {
+        new_core_objects = chaz_Util_strdup(obj_file);
+    }
+    else {
+        new_core_objects = chaz_Util_join(" ", self->core_objects, obj_file,
+                                          NULL);
+    }
+    free(self->core_objects);
+    self->core_objects = new_core_objects;
+}
+
+static void
 S_cfh_file_callback(const char *dir, char *file, void *context) {
-    SourceFileContext *sfc = (SourceFileContext*)context;
+    cfish_MakeFile *self = (cfish_MakeFile*)context;
     const char *dir_sep = chaz_OS_dir_sep();
     char *cfh_file;
 
@@ -8904,7 +8911,7 @@ S_cfh_file_callback(const char *dir, char *file, void 
*context) {
     }
 
     cfh_file = chaz_Util_join(dir_sep, dir, file, NULL);
-    chaz_MakeVar_append(sfc->var, cfh_file);
+    chaz_MakeVar_append(self->cfh_var, cfh_file);
     free(cfh_file);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e169fbe3/runtime/common/charmonizer.main
----------------------------------------------------------------------
diff --git a/runtime/common/charmonizer.main b/runtime/common/charmonizer.main
index f5e7c92..4a425f3 100644
--- a/runtime/common/charmonizer.main
+++ b/runtime/common/charmonizer.main
@@ -41,6 +41,8 @@
 
 typedef struct cfish_MakeFile {
     chaz_MakeFile *makefile;
+    chaz_MakeVar  *obj_var;
+    chaz_MakeVar  *cfh_var;
     chaz_CLI      *cli;
 
     /* Directories and files. */
@@ -50,7 +52,7 @@ typedef struct cfish_MakeFile {
     char        *autogen_src_dir;
     char        *autogen_inc_dir;
     char        *autogen_target;
-    const char **autogen_src_files;
+    char        *core_objects;
 
     /* Libraries. */
     chaz_Lib *shared_lib;
@@ -59,10 +61,6 @@ typedef struct cfish_MakeFile {
     char     *static_lib_filename;
 } cfish_MakeFile;
 
-typedef struct SourceFileContext {
-    chaz_MakeVar *var;
-} SourceFileContext;
-
 static const char cfish_version[]       = "0.5.0";
 static const char cfish_major_version[] = "0.5";
 
@@ -91,6 +89,9 @@ static void
 S_c_file_callback(const char *dir, char *file, void *context);
 
 static void
+S_add_core_object(cfish_MakeFile *self, const char *obj_file);
+
+static void
 S_cfh_file_callback(const char *dir, char *file, void *context);
 
 static int
@@ -186,6 +187,7 @@ int main(int argc, const char **argv) {
                                 mf->shared_lib_filename);
         chaz_ConfWriter_add_def("STATIC_LIB_FILENAME",
                                 mf->static_lib_filename);
+        chaz_ConfWriter_add_def("CORE_OBJECTS", mf->core_objects);
         cfish_MakeFile_destroy(mf);
     }
 
@@ -270,6 +272,9 @@ cfish_MakeFile_new(chaz_CLI *cli) {
     cfish_MakeFile *self = malloc(sizeof(cfish_MakeFile));
 
     self->makefile = chaz_MakeFile_new();
+    self->obj_var  = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_OBJS",
+                                           NULL);
+    self->cfh_var  = NULL;
     self->cli      = cli;
 
     self->base_dir = "..";
@@ -281,42 +286,18 @@ cfish_MakeFile_new(chaz_CLI *cli) {
         = chaz_Util_join(dir_sep, "autogen", "hierarchy.json", NULL);
 
     if (strcmp(chaz_CLI_strval(cli, "host"), "go") == 0) {
-        static const char *go_autogen_src_files[] = {
-            "cfish_parcel",
-            "testcfish_parcel",
-            NULL
-        };
+        /* TODO: Let Go bindings build code in "ext". */
         self->host_src_dir = "ext";
-        self->autogen_src_files = go_autogen_src_files;
     }
     else if (chaz_CLI_defined(cli, "enable-python")) {
-        static const char *python_autogen_src_files[] = {
-            "cfish_parcel",
-            "testcfish_parcel",
-            NULL
-        };
+        /* TODO: Let Python bindings build code in "cfext". */
         self->host_src_dir = "cfext";
-        self->autogen_src_files = python_autogen_src_files;
-    }
-    else if (chaz_CLI_defined(cli, "enable-perl")) {
-        static const char *perl_autogen_src_files[] = {
-            "cfish_parcel",
-            "cfish_perl",
-            "testcfish_parcel",
-            "testcfish_perl",
-            NULL
-        };
-        self->host_src_dir = "xs";
-        self->autogen_src_files = perl_autogen_src_files;
     }
-    else {
-        static const char *c_autogen_src_files[] = {
-            "cfish_parcel",
-            "testcfish_parcel",
-            NULL
-        };
+    else if (strcmp(chaz_CLI_strval(cli, "host"), "c") == 0) {
         self->host_src_dir = "src";
-        self->autogen_src_files = c_autogen_src_files;
+    }
+    else {
+        self->host_src_dir = NULL;
     }
 
     self->shared_lib = chaz_Lib_new_shared("cfish", cfish_version,
@@ -324,6 +305,7 @@ cfish_MakeFile_new(chaz_CLI *cli) {
     self->static_lib = chaz_Lib_new_static("clownfish");
     self->shared_lib_filename = chaz_Lib_filename(self->shared_lib);
     self->static_lib_filename = chaz_Lib_filename(self->static_lib);
+    self->core_objects = chaz_Util_strdup("");
 
     return self;
 }
@@ -341,13 +323,18 @@ cfish_MakeFile_destroy(cfish_MakeFile *self) {
     chaz_Lib_destroy(self->static_lib);
     free(self->shared_lib_filename);
     free(self->static_lib_filename);
+    free(self->core_objects);
 
     free(self);
 }
 
 static void
 cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags *extra_link_flags) {
-    SourceFileContext sfc;
+    static const char *const autogen_src_files[] = {
+        "cfish_parcel",
+        "testcfish_parcel",
+        NULL
+    };
 
     const char *dir_sep  = chaz_OS_dir_sep();
     const char *obj_ext  = chaz_CC_obj_ext();
@@ -386,7 +373,9 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags 
*extra_link_flags) {
 
     chaz_CFlags_add_include_dir(makefile_cflags, ".");
     chaz_CFlags_add_include_dir(makefile_cflags, self->core_dir);
-    chaz_CFlags_add_include_dir(makefile_cflags, self->host_src_dir);
+    if (self->host_src_dir) {
+        chaz_CFlags_add_include_dir(makefile_cflags, self->host_src_dir);
+    }
     chaz_CFlags_add_include_dir(makefile_cflags, self->autogen_inc_dir);
 
     var = chaz_MakeFile_add_var(self->makefile, "CFLAGS", NULL);
@@ -398,15 +387,15 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags 
*extra_link_flags) {
 
     /* Object files */
 
-    var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_OBJS", NULL);
-    sfc.var = var;
-    chaz_Make_list_files(self->host_src_dir, "c", S_c_file_callback, &sfc);
-    chaz_Make_list_files(self->core_dir,     "c", S_c_file_callback, &sfc);
+    if (self->host_src_dir) {
+        chaz_Make_list_files(self->host_src_dir, "c", S_c_file_callback, self);
+    }
+    chaz_Make_list_files(self->core_dir, "c", S_c_file_callback, self);
 
-    for (i = 0; self->autogen_src_files[i] != NULL; ++i) {
+    for (i = 0; autogen_src_files[i] != NULL; ++i) {
         char *path = chaz_Util_join("", self->autogen_src_dir, dir_sep,
-                                    self->autogen_src_files[i], obj_ext, NULL);
-        chaz_MakeVar_append(var, path);
+                                    autogen_src_files[i], obj_ext, NULL);
+        S_add_core_object(self, path);
         free(path);
     }
 
@@ -414,15 +403,17 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags 
*extra_link_flags) {
 
     chaz_MakeFile_add_rule(self->makefile, "all", self->shared_lib_filename);
     chaz_MakeFile_add_rule(self->makefile, "static", 
self->static_lib_filename);
+    chaz_MakeFile_add_rule(self->makefile, "core_objects",
+                           "$(CLOWNFISH_OBJS)");
 
     if (strcmp(chaz_CLI_strval(self->cli, "host"), "c") == 0) {
         cfish_MakeFile_write_c_cfc_rules(self);
     }
 
     /* Needed for parallel builds. */
-    for (i = 0; self->autogen_src_files[i] != NULL; ++i) {
+    for (i = 0; autogen_src_files[i] != NULL; ++i) {
         char *path = chaz_Util_join("", self->autogen_src_dir, dir_sep,
-                                    self->autogen_src_files[i], ".c", NULL);
+                                    autogen_src_files[i], ".c", NULL);
         chaz_MakeFile_add_rule(self->makefile, path, self->autogen_target);
         free(path);
     }
@@ -452,7 +443,6 @@ cfish_MakeFile_write(cfish_MakeFile *self, chaz_CFlags 
*extra_link_flags) {
 
 static void
 cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
-    SourceFileContext sfc;
     chaz_MakeVar  *var;
     chaz_MakeRule *rule;
 
@@ -470,9 +460,9 @@ cfish_MakeFile_write_c_cfc_rules(cfish_MakeFile *self) {
     rule = chaz_MakeFile_add_rule(self->makefile, cfc_exe, NULL);
     chaz_MakeRule_add_make_command(rule, cfc_dir, NULL);
 
-    var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_HEADERS", NULL);
-    sfc.var = var;
-    chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, &sfc);
+    self->cfh_var = chaz_MakeFile_add_var(self->makefile, "CLOWNFISH_HEADERS",
+                                          NULL);
+    chaz_Make_list_files(self->core_dir, "cfh", S_cfh_file_callback, self);
 
     rule = chaz_MakeFile_add_rule(self->makefile, self->autogen_target, 
cfc_exe);
     chaz_MakeRule_add_prereq(rule, "$(CLOWNFISH_HEADERS)");
@@ -592,7 +582,7 @@ cfish_MakeFile_write_c_test_rules(cfish_MakeFile *self) {
 
 static void
 S_c_file_callback(const char *dir, char *file, void *context) {
-    SourceFileContext *sfc = (SourceFileContext*)context;
+    cfish_MakeFile *self = (cfish_MakeFile*)context;
     const char *dir_sep = chaz_OS_dir_sep();
     const char *obj_ext = chaz_CC_obj_ext();
     size_t file_len = strlen(file);
@@ -606,13 +596,30 @@ S_c_file_callback(const char *dir, char *file, void 
*context) {
     file[file_len-2] = '\0';
 
     obj_file = chaz_Util_join("", dir, dir_sep, file, obj_ext, NULL);
-    chaz_MakeVar_append(sfc->var, obj_file);
+    S_add_core_object(self, obj_file);
     free(obj_file);
 }
 
 static void
+S_add_core_object(cfish_MakeFile *self, const char *obj_file) {
+    char *new_core_objects;
+
+    chaz_MakeVar_append(self->obj_var, obj_file);
+
+    if (self->core_objects[0] == '\0') {
+        new_core_objects = chaz_Util_strdup(obj_file);
+    }
+    else {
+        new_core_objects = chaz_Util_join(" ", self->core_objects, obj_file,
+                                          NULL);
+    }
+    free(self->core_objects);
+    self->core_objects = new_core_objects;
+}
+
+static void
 S_cfh_file_callback(const char *dir, char *file, void *context) {
-    SourceFileContext *sfc = (SourceFileContext*)context;
+    cfish_MakeFile *self = (cfish_MakeFile*)context;
     const char *dir_sep = chaz_OS_dir_sep();
     char *cfh_file;
 
@@ -622,7 +629,7 @@ S_cfh_file_callback(const char *dir, char *file, void 
*context) {
     }
 
     cfh_file = chaz_Util_join(dir_sep, dir, file, NULL);
-    chaz_MakeVar_append(sfc->var, cfh_file);
+    chaz_MakeVar_append(self->cfh_var, cfh_file);
     free(cfh_file);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e169fbe3/runtime/perl/.gitignore
----------------------------------------------------------------------
diff --git a/runtime/perl/.gitignore b/runtime/perl/.gitignore
index 6221610..4e0ff0f 100644
--- a/runtime/perl/.gitignore
+++ b/runtime/perl/.gitignore
@@ -4,6 +4,7 @@
 /Charmony.pm
 /MYMETA.json
 /MYMETA.yml
+/Makefile
 /_build/
 /autogen/
 /blib/

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e169fbe3/runtime/perl/buildlib/Clownfish/Build.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/buildlib/Clownfish/Build.pm 
b/runtime/perl/buildlib/Clownfish/Build.pm
index 061759d..8ae957f 100644
--- a/runtime/perl/buildlib/Clownfish/Build.pm
+++ b/runtime/perl/buildlib/Clownfish/Build.pm
@@ -68,7 +68,8 @@ sub new {
     $args{clownfish_params} = {
         autogen_header => _autogen_header(),
         include        => [],                  # Don't use default includes.
-        source => [ $CORE_SOURCE_DIR, $XS_SOURCE_DIR ],
+        source   => [ $CORE_SOURCE_DIR ],
+        c_source => [ $XS_SOURCE_DIR ],
     };
     my $self = $class->SUPER::new( recursive_test_files => 1, %args );
 
@@ -83,6 +84,7 @@ sub new {
         $self->extra_compiler_flags(@$extra_cflags);
     }
 
+    $self->charmonizer_params( create_makefile => 1 );
     $self->charmonizer_params( charmonizer_c => $CHARMONIZER_C );
 
     return $self;

Reply via email to