Implement chaz_MakeFile_add_obj_dir_rule
Add a rule to create object files in a separate directory and/or use
custom compiler flags for all source files in a directory.
This works with nmake and GNU make but isn't POSIX-compatible.
diff --git a/src/Charmonizer/Core/Make.c b/src/Charmonizer/Core/Make.c
index 1063bf3..71820bc 100644
--- a/src/Charmonizer/Core/Make.c
+++ b/src/Charmonizer/Core/Make.c
@@ -544,6 +544,70 @@
free(src);
}
+chaz_MakeRule*
+chaz_MakeFile_add_obj_dir_rule(chaz_MakeFile *makefile, const char *src_dir,
+ const char *obj_dir, chaz_CFlags *cflags) {
+ chaz_MakeRule *rule;
+ const char *dir_sep = chaz_OS_dir_sep();
+ const char *obj_ext = chaz_CC_obj_ext();
+ const char *mkdir_command = NULL;
+ const char *cflags_string = NULL;
+ char *target = NULL;
+ char *prereq = NULL;
+ char *cc_command = NULL;
+
+ if (obj_dir == NULL) {
+ obj_dir = src_dir;
+ }
+
+ if (strcmp(chaz_Make.make_command, "nmake") == 0) {
+ /* nmake-style search paths in inference rules. */
+ target = chaz_Util_join("", "{", src_dir, "\\}.c{", obj_dir,
+ "\\}", obj_ext, NULL);
+ }
+ else {
+ /* GNU make pattern match. TODO: This is not POSIX-compatible. */
+ target = chaz_Util_join("", obj_dir, dir_sep, "%", obj_ext, NULL);
+ prereq = chaz_Util_join(dir_sep, src_dir, "%.c", NULL);
+ }
+
+ rule = chaz_MakeFile_add_rule(makefile, target, prereq);
+
+ if (chaz_Make.shell_type == CHAZ_OS_POSIX) {
+ mkdir_command = "@mkdir -p $$(dirname $@)";
+ }
+ else if (chaz_Make.shell_type == CHAZ_OS_CMD_EXE) {
+ mkdir_command = "@for %F in ($@) do @mkdir %~dpF 2>nul";
+ }
+ else {
+ chaz_Util_die("Unsupported shell type: %d", chaz_Make.shell_type);
+ }
+
+ if (cflags == NULL) {
+ cflags_string = "$(CFLAGS)";
+ }
+ else {
+ cflags_string = chaz_CFlags_get_string(cflags);
+ }
+
+ if (chaz_CC_msvc_version_num()) {
+ cc_command = chaz_Util_join(" ", "$(CC) /nologo", cflags_string,
+ "/c $< /Fo$@", NULL);
+ }
+ else {
+ cc_command = chaz_Util_join(" ", "$(CC)", cflags_string, "-c $< -o $@",
+ NULL);
+ }
+
+ chaz_MakeRule_add_command(rule, mkdir_command);
+ chaz_MakeRule_add_command(rule, cc_command);
+
+ free(cc_command);
+ free(prereq);
+ free(target);
+ return rule;
+}
+
void
chaz_MakeFile_write(chaz_MakeFile *makefile) {
FILE *out;
diff --git a/src/Charmonizer/Core/Make.h b/src/Charmonizer/Core/Make.h
index 50fc301..cf8c78f 100644
--- a/src/Charmonizer/Core/Make.h
+++ b/src/Charmonizer/Core/Make.h
@@ -191,6 +191,17 @@
chaz_MakeFile_override_cflags(chaz_MakeFile *makefile, const char *obj,
chaz_CFlags *cflags);
+/** Add a rule to create object files in a separate directory and/or use
+ * custom compiler flags for all source files in a directory.
+ *
+ * @param src_dir The root directory of source files.
+ * @param obj_dir The directory for object files. Same as `src_dir` if NULL.
+ * @param cflags Compiler flags. Use `$(CFLAGS)` if NULL.
+ */
+chaz_MakeRule*
+chaz_MakeFile_add_obj_dir_rule(chaz_MakeFile *makefile, const char *src_dir,
+ const char *obj_dir, chaz_CFlags *cflags);
+
/** Write the makefile to a file named 'Makefile' in the current directory.
*
* @param makefile The makefile.