Rework Makefile API for binaries
Expose a higher level API to build binaries with make. The new
chaz_MakeBinary class allows to scan a directory for source files
and to pass separate compiler flags for each binary.
Improve building of shared libaries:
- Add compatibility version on Darwin (Mach-O).
- Build import library with GCC on Windows.
- Add soname with Sun CC (untested).
Remove the chaz_Library class.
Rework detection of the platform's make utility. We don't use this
information for now, so it's purely informative.
diff --git a/Makefile b/Makefile
index 8221cac..c5ffdd9 100644
--- a/Makefile
+++ b/Makefile
@@ -27,11 +27,11 @@
TESTS= TestDirManip TestFuncMacro TestHeaders TestIntegers TestLargeFiles TestUnusedVars TestVariadicMacros
-OBJS= charmonize.o src/Charmonizer/Core/CFlags.o src/Charmonizer/Core/CLI.o src/Charmonizer/Core/Compiler.o src/Charmonizer/Core/ConfWriter.o src/Charmonizer/Core/ConfWriterC.o src/Charmonizer/Core/ConfWriterPerl.o src/Charmonizer/Core/ConfWriterPython.o src/Charmonizer/Core/ConfWriterRuby.o src/Charmonizer/Core/HeaderChecker.o src/Charmonizer/Core/Library.o src/Charmonizer/Core/Make.o src/Charmonizer/Core/OperatingSystem.o src/Charmonizer/Core/Util.o src/Charmonizer/Probe.o src/Charmonizer/Probe/AtomicOps.o src/Charmonizer/Probe/Booleans.o src/Charmonizer/Probe/BuildEnv.o src/Charmonizer/Probe/DirManip.o src/Charmonizer/Probe/Floats.o src/Charmonizer/Probe/FuncMacro.o src/Charmonizer/Probe/Headers.o src/Charmonizer/Probe/Integers.o src/Charmonizer/Probe/LargeFiles.o src/Charmonizer/Probe/Memory.o src/Charmonizer/Probe/RegularExpressions.o src/Charmonizer/Probe/Strings.o src/Charmonizer/Probe/SymbolVisibility.o src/Charmonizer/Probe/UnusedVars.o src/Charmonizer/Probe/VariadicMacros.o
+OBJS= charmonize.o src/Charmonizer/Core/CFlags.o src/Charmonizer/Core/CLI.o src/Charmonizer/Core/Compiler.o src/Charmonizer/Core/ConfWriter.o src/Charmonizer/Core/ConfWriterC.o src/Charmonizer/Core/ConfWriterPerl.o src/Charmonizer/Core/ConfWriterPython.o src/Charmonizer/Core/ConfWriterRuby.o src/Charmonizer/Core/HeaderChecker.o src/Charmonizer/Core/Make.o src/Charmonizer/Core/OperatingSystem.o src/Charmonizer/Core/Util.o src/Charmonizer/Probe.o src/Charmonizer/Probe/AtomicOps.o src/Charmonizer/Probe/Booleans.o src/Charmonizer/Probe/BuildEnv.o src/Charmonizer/Probe/DirManip.o src/Charmonizer/Probe/Floats.o src/Charmonizer/Probe/FuncMacro.o src/Charmonizer/Probe/Headers.o src/Charmonizer/Probe/Integers.o src/Charmonizer/Probe/LargeFiles.o src/Charmonizer/Probe/Memory.o src/Charmonizer/Probe/RegularExpressions.o src/Charmonizer/Probe/Strings.o src/Charmonizer/Probe/SymbolVisibility.o src/Charmonizer/Probe/UnusedVars.o src/Charmonizer/Probe/VariadicMacros.o
TEST_OBJS= src/Charmonizer/Test.o src/Charmonizer/Test/TestDirManip.o src/Charmonizer/Test/TestFuncMacro.o src/Charmonizer/Test/TestHeaders.o src/Charmonizer/Test/TestIntegers.o src/Charmonizer/Test/TestLargeFiles.o src/Charmonizer/Test/TestUnusedVars.o src/Charmonizer/Test/TestVariadicMacros.o
-HEADERS= src/Charmonizer/Core/CFlags.h src/Charmonizer/Core/CLI.h src/Charmonizer/Core/Compiler.h src/Charmonizer/Core/ConfWriter.h src/Charmonizer/Core/ConfWriterC.h src/Charmonizer/Core/ConfWriterPerl.h src/Charmonizer/Core/ConfWriterPython.h src/Charmonizer/Core/ConfWriterRuby.h src/Charmonizer/Core/Defines.h src/Charmonizer/Core/HeaderChecker.h src/Charmonizer/Core/Library.h src/Charmonizer/Core/Make.h src/Charmonizer/Core/OperatingSystem.h src/Charmonizer/Core/Util.h src/Charmonizer/Probe.h src/Charmonizer/Probe/AtomicOps.h src/Charmonizer/Probe/Booleans.h src/Charmonizer/Probe/BuildEnv.h src/Charmonizer/Probe/DirManip.h src/Charmonizer/Probe/Floats.h src/Charmonizer/Probe/FuncMacro.h src/Charmonizer/Probe/Headers.h src/Charmonizer/Probe/Integers.h src/Charmonizer/Probe/LargeFiles.h src/Charmonizer/Probe/Memory.h src/Charmonizer/Probe/RegularExpressions.h src/Charmonizer/Probe/Strings.h src/Charmonizer/Probe/SymbolVisibility.h src/Charmonizer/Probe/UnusedVars.h src/Charmonizer/Probe/VariadicMacros.h src/Charmonizer/Test.h
+HEADERS= src/Charmonizer/Core/CFlags.h src/Charmonizer/Core/CLI.h src/Charmonizer/Core/Compiler.h src/Charmonizer/Core/ConfWriter.h src/Charmonizer/Core/ConfWriterC.h src/Charmonizer/Core/ConfWriterPerl.h src/Charmonizer/Core/ConfWriterPython.h src/Charmonizer/Core/ConfWriterRuby.h src/Charmonizer/Core/Defines.h src/Charmonizer/Core/HeaderChecker.h src/Charmonizer/Core/Make.h src/Charmonizer/Core/OperatingSystem.h src/Charmonizer/Core/Util.h src/Charmonizer/Probe.h src/Charmonizer/Probe/AtomicOps.h src/Charmonizer/Probe/Booleans.h src/Charmonizer/Probe/BuildEnv.h src/Charmonizer/Probe/DirManip.h src/Charmonizer/Probe/Floats.h src/Charmonizer/Probe/FuncMacro.h src/Charmonizer/Probe/Headers.h src/Charmonizer/Probe/Integers.h src/Charmonizer/Probe/LargeFiles.h src/Charmonizer/Probe/Memory.h src/Charmonizer/Probe/RegularExpressions.h src/Charmonizer/Probe/Strings.h src/Charmonizer/Probe/SymbolVisibility.h src/Charmonizer/Probe/UnusedVars.h src/Charmonizer/Probe/VariadicMacros.h src/Charmonizer/Test.h
CLEANABLE= $(OBJS) $(PROGNAME) $(CHARMONY_H) $(TEST_OBJS) $(TESTS)
diff --git a/Makefile.MSVC b/Makefile.MSVC
index 155140c..ec9654a 100644
--- a/Makefile.MSVC
+++ b/Makefile.MSVC
@@ -27,11 +27,11 @@
TESTS= TestDirManip.exe TestFuncMacro.exe TestHeaders.exe TestIntegers.exe TestLargeFiles.exe TestUnusedVars.exe TestVariadicMacros.exe
-OBJS= charmonize.obj src\Charmonizer\Core\CFlags.obj src\Charmonizer\Core\CLI.obj src\Charmonizer\Core\Compiler.obj src\Charmonizer\Core\ConfWriter.obj src\Charmonizer\Core\ConfWriterC.obj src\Charmonizer\Core\ConfWriterPerl.obj src\Charmonizer\Core\ConfWriterPython.obj src\Charmonizer\Core\ConfWriterRuby.obj src\Charmonizer\Core\HeaderChecker.obj src\Charmonizer\Core\Library.obj src\Charmonizer\Core\Make.obj src\Charmonizer\Core\OperatingSystem.obj src\Charmonizer\Core\Util.obj src\Charmonizer\Probe.obj src\Charmonizer\Probe\AtomicOps.obj src\Charmonizer\Probe\Booleans.obj src\Charmonizer\Probe\BuildEnv.obj src\Charmonizer\Probe\DirManip.obj src\Charmonizer\Probe\Floats.obj src\Charmonizer\Probe\FuncMacro.obj src\Charmonizer\Probe\Headers.obj src\Charmonizer\Probe\Integers.obj src\Charmonizer\Probe\LargeFiles.obj src\Charmonizer\Probe\Memory.obj src\Charmonizer\Probe\RegularExpressions.obj src\Charmonizer\Probe\Strings.obj src\Charmonizer\Probe\SymbolVisibility.obj src\Charmonizer\Probe\UnusedVars.obj src\Charmonizer\Probe\VariadicMacros.obj
+OBJS= charmonize.obj src\Charmonizer\Core\CFlags.obj src\Charmonizer\Core\CLI.obj src\Charmonizer\Core\Compiler.obj src\Charmonizer\Core\ConfWriter.obj src\Charmonizer\Core\ConfWriterC.obj src\Charmonizer\Core\ConfWriterPerl.obj src\Charmonizer\Core\ConfWriterPython.obj src\Charmonizer\Core\ConfWriterRuby.obj src\Charmonizer\Core\HeaderChecker.obj src\Charmonizer\Core\Make.obj src\Charmonizer\Core\OperatingSystem.obj src\Charmonizer\Core\Util.obj src\Charmonizer\Probe.obj src\Charmonizer\Probe\AtomicOps.obj src\Charmonizer\Probe\Booleans.obj src\Charmonizer\Probe\BuildEnv.obj src\Charmonizer\Probe\DirManip.obj src\Charmonizer\Probe\Floats.obj src\Charmonizer\Probe\FuncMacro.obj src\Charmonizer\Probe\Headers.obj src\Charmonizer\Probe\Integers.obj src\Charmonizer\Probe\LargeFiles.obj src\Charmonizer\Probe\Memory.obj src\Charmonizer\Probe\RegularExpressions.obj src\Charmonizer\Probe\Strings.obj src\Charmonizer\Probe\SymbolVisibility.obj src\Charmonizer\Probe\UnusedVars.obj src\Charmonizer\Probe\VariadicMacros.obj
TEST_OBJS= src\Charmonizer\Test.obj src\Charmonizer\Test\TestDirManip.obj src\Charmonizer\Test\TestFuncMacro.obj src\Charmonizer\Test\TestHeaders.obj src\Charmonizer\Test\TestIntegers.obj src\Charmonizer\Test\TestLargeFiles.obj src\Charmonizer\Test\TestUnusedVars.obj src\Charmonizer\Test\TestVariadicMacros.obj
-HEADERS= src\Charmonizer\Core\CFlags.h src\Charmonizer\Core\CLI.h src\Charmonizer\Core\Compiler.h src\Charmonizer\Core\ConfWriter.h src\Charmonizer\Core\ConfWriterC.h src\Charmonizer\Core\ConfWriterPerl.h src\Charmonizer\Core\ConfWriterPython.h src\Charmonizer\Core\ConfWriterRuby.h src\Charmonizer\Core\Defines.h src\Charmonizer\Core\HeaderChecker.h src\Charmonizer\Core\Library.h src\Charmonizer\Core\Make.h src\Charmonizer\Core\OperatingSystem.h src\Charmonizer\Core\Util.h src\Charmonizer\Probe.h src\Charmonizer\Probe\AtomicOps.h src\Charmonizer\Probe\Booleans.h src\Charmonizer\Probe\BuildEnv.h src\Charmonizer\Probe\DirManip.h src\Charmonizer\Probe\Floats.h src\Charmonizer\Probe\FuncMacro.h src\Charmonizer\Probe\Headers.h src\Charmonizer\Probe\Integers.h src\Charmonizer\Probe\LargeFiles.h src\Charmonizer\Probe\Memory.h src\Charmonizer\Probe\RegularExpressions.h src\Charmonizer\Probe\Strings.h src\Charmonizer\Probe\SymbolVisibility.h src\Charmonizer\Probe\UnusedVars.h src\Charmonizer\Probe\VariadicMacros.h src\Charmonizer\Test.h
+HEADERS= src\Charmonizer\Core\CFlags.h src\Charmonizer\Core\CLI.h src\Charmonizer\Core\Compiler.h src\Charmonizer\Core\ConfWriter.h src\Charmonizer\Core\ConfWriterC.h src\Charmonizer\Core\ConfWriterPerl.h src\Charmonizer\Core\ConfWriterPython.h src\Charmonizer\Core\ConfWriterRuby.h src\Charmonizer\Core\Defines.h src\Charmonizer\Core\HeaderChecker.h src\Charmonizer\Core\Make.h src\Charmonizer\Core\OperatingSystem.h src\Charmonizer\Core\Util.h src\Charmonizer\Probe.h src\Charmonizer\Probe\AtomicOps.h src\Charmonizer\Probe\Booleans.h src\Charmonizer\Probe\BuildEnv.h src\Charmonizer\Probe\DirManip.h src\Charmonizer\Probe\Floats.h src\Charmonizer\Probe\FuncMacro.h src\Charmonizer\Probe\Headers.h src\Charmonizer\Probe\Integers.h src\Charmonizer\Probe\LargeFiles.h src\Charmonizer\Probe\Memory.h src\Charmonizer\Probe\RegularExpressions.h src\Charmonizer\Probe\Strings.h src\Charmonizer\Probe\SymbolVisibility.h src\Charmonizer\Probe\UnusedVars.h src\Charmonizer\Probe\VariadicMacros.h src\Charmonizer\Test.h
CLEANABLE= $(OBJS) $(PROGNAME) $(CHARMONY_H) $(TEST_OBJS) $(TESTS) *.pdb
diff --git a/Makefile.MinGW b/Makefile.MinGW
index 0c3104a..3cbad7f 100644
--- a/Makefile.MinGW
+++ b/Makefile.MinGW
@@ -27,11 +27,11 @@
TESTS= TestDirManip.exe TestFuncMacro.exe TestHeaders.exe TestIntegers.exe TestLargeFiles.exe TestUnusedVars.exe TestVariadicMacros.exe
-OBJS= charmonize.o src\Charmonizer\Core\CFlags.o src\Charmonizer\Core\CLI.o src\Charmonizer\Core\Compiler.o src\Charmonizer\Core\ConfWriter.o src\Charmonizer\Core\ConfWriterC.o src\Charmonizer\Core\ConfWriterPerl.o src\Charmonizer\Core\ConfWriterPython.o src\Charmonizer\Core\ConfWriterRuby.o src\Charmonizer\Core\HeaderChecker.o src\Charmonizer\Core\Library.o src\Charmonizer\Core\Make.o src\Charmonizer\Core\OperatingSystem.o src\Charmonizer\Core\Util.o src\Charmonizer\Probe.o src\Charmonizer\Probe\AtomicOps.o src\Charmonizer\Probe\Booleans.o src\Charmonizer\Probe\BuildEnv.o src\Charmonizer\Probe\DirManip.o src\Charmonizer\Probe\Floats.o src\Charmonizer\Probe\FuncMacro.o src\Charmonizer\Probe\Headers.o src\Charmonizer\Probe\Integers.o src\Charmonizer\Probe\LargeFiles.o src\Charmonizer\Probe\Memory.o src\Charmonizer\Probe\RegularExpressions.o src\Charmonizer\Probe\Strings.o src\Charmonizer\Probe\SymbolVisibility.o src\Charmonizer\Probe\UnusedVars.o src\Charmonizer\Probe\VariadicMacros.o
+OBJS= charmonize.o src\Charmonizer\Core\CFlags.o src\Charmonizer\Core\CLI.o src\Charmonizer\Core\Compiler.o src\Charmonizer\Core\ConfWriter.o src\Charmonizer\Core\ConfWriterC.o src\Charmonizer\Core\ConfWriterPerl.o src\Charmonizer\Core\ConfWriterPython.o src\Charmonizer\Core\ConfWriterRuby.o src\Charmonizer\Core\HeaderChecker.o src\Charmonizer\Core\Make.o src\Charmonizer\Core\OperatingSystem.o src\Charmonizer\Core\Util.o src\Charmonizer\Probe.o src\Charmonizer\Probe\AtomicOps.o src\Charmonizer\Probe\Booleans.o src\Charmonizer\Probe\BuildEnv.o src\Charmonizer\Probe\DirManip.o src\Charmonizer\Probe\Floats.o src\Charmonizer\Probe\FuncMacro.o src\Charmonizer\Probe\Headers.o src\Charmonizer\Probe\Integers.o src\Charmonizer\Probe\LargeFiles.o src\Charmonizer\Probe\Memory.o src\Charmonizer\Probe\RegularExpressions.o src\Charmonizer\Probe\Strings.o src\Charmonizer\Probe\SymbolVisibility.o src\Charmonizer\Probe\UnusedVars.o src\Charmonizer\Probe\VariadicMacros.o
TEST_OBJS= src\Charmonizer\Test.o src\Charmonizer\Test\TestDirManip.o src\Charmonizer\Test\TestFuncMacro.o src\Charmonizer\Test\TestHeaders.o src\Charmonizer\Test\TestIntegers.o src\Charmonizer\Test\TestLargeFiles.o src\Charmonizer\Test\TestUnusedVars.o src\Charmonizer\Test\TestVariadicMacros.o
-HEADERS= src\Charmonizer\Core\CFlags.h src\Charmonizer\Core\CLI.h src\Charmonizer\Core\Compiler.h src\Charmonizer\Core\ConfWriter.h src\Charmonizer\Core\ConfWriterC.h src\Charmonizer\Core\ConfWriterPerl.h src\Charmonizer\Core\ConfWriterPython.h src\Charmonizer\Core\ConfWriterRuby.h src\Charmonizer\Core\Defines.h src\Charmonizer\Core\HeaderChecker.h src\Charmonizer\Core\Library.h src\Charmonizer\Core\Make.h src\Charmonizer\Core\OperatingSystem.h src\Charmonizer\Core\Util.h src\Charmonizer\Probe.h src\Charmonizer\Probe\AtomicOps.h src\Charmonizer\Probe\Booleans.h src\Charmonizer\Probe\BuildEnv.h src\Charmonizer\Probe\DirManip.h src\Charmonizer\Probe\Floats.h src\Charmonizer\Probe\FuncMacro.h src\Charmonizer\Probe\Headers.h src\Charmonizer\Probe\Integers.h src\Charmonizer\Probe\LargeFiles.h src\Charmonizer\Probe\Memory.h src\Charmonizer\Probe\RegularExpressions.h src\Charmonizer\Probe\Strings.h src\Charmonizer\Probe\SymbolVisibility.h src\Charmonizer\Probe\UnusedVars.h src\Charmonizer\Probe\VariadicMacros.h src\Charmonizer\Test.h
+HEADERS= src\Charmonizer\Core\CFlags.h src\Charmonizer\Core\CLI.h src\Charmonizer\Core\Compiler.h src\Charmonizer\Core\ConfWriter.h src\Charmonizer\Core\ConfWriterC.h src\Charmonizer\Core\ConfWriterPerl.h src\Charmonizer\Core\ConfWriterPython.h src\Charmonizer\Core\ConfWriterRuby.h src\Charmonizer\Core\Defines.h src\Charmonizer\Core\HeaderChecker.h src\Charmonizer\Core\Make.h src\Charmonizer\Core\OperatingSystem.h src\Charmonizer\Core\Util.h src\Charmonizer\Probe.h src\Charmonizer\Probe\AtomicOps.h src\Charmonizer\Probe\Booleans.h src\Charmonizer\Probe\BuildEnv.h src\Charmonizer\Probe\DirManip.h src\Charmonizer\Probe\Floats.h src\Charmonizer\Probe\FuncMacro.h src\Charmonizer\Probe\Headers.h src\Charmonizer\Probe\Integers.h src\Charmonizer\Probe\LargeFiles.h src\Charmonizer\Probe\Memory.h src\Charmonizer\Probe\RegularExpressions.h src\Charmonizer\Probe\Strings.h src\Charmonizer\Probe\SymbolVisibility.h src\Charmonizer\Probe\UnusedVars.h src\Charmonizer\Probe\VariadicMacros.h src\Charmonizer\Test.h
CLEANABLE= $(OBJS) $(PROGNAME) $(CHARMONY_H) $(TEST_OBJS) $(TESTS)
diff --git a/buildbin/meld.pl b/buildbin/meld.pl
index 48a5885..b4db46c 100755
--- a/buildbin/meld.pl
+++ b/buildbin/meld.pl
@@ -67,7 +67,6 @@
}
my @core = qw(
- Library
CFlags
CLI
Compiler
diff --git a/src/Charmonizer/Core/CFlags.c b/src/Charmonizer/Core/CFlags.c
index 1c177b5..a1f4684 100644
--- a/src/Charmonizer/Core/CFlags.c
+++ b/src/Charmonizer/Core/CFlags.c
@@ -20,7 +20,6 @@
#include "Charmonizer/Core/Compiler.h"
#include "Charmonizer/Core/Util.h"
#include "Charmonizer/Core/OperatingSystem.h"
-#include "Charmonizer/Core/Library.h"
struct chaz_CFlags {
int style;
@@ -244,55 +243,44 @@
}
void
-chaz_CFlags_link_shared_library(chaz_CFlags *flags) {
- const char *string;
+chaz_CFlags_link_shared_library(chaz_CFlags *flags, const char *basename,
+ const char *version,
+ const char *major_version) {
+ char *string = NULL;
+
if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
- string = "/DLL";
+ string = chaz_Util_strdup("/DLL");
}
else if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
- if (chaz_CC_binary_format() == CHAZ_CC_BINFMT_MACHO) {
- string = "-dynamiclib";
+ int binary_format = chaz_CC_binary_format();
+
+ if (binary_format == CHAZ_CC_BINFMT_MACHO) {
+ string = chaz_Util_join(" ", "-dynamiclib", "-current_version",
+ version, "-compatibility_version",
+ major_version, NULL);
}
- else {
- string = "-shared";
+ else if (binary_format == CHAZ_CC_BINFMT_ELF) {
+ string = chaz_Util_join("", "-shared -Wl,-soname,lib", basename,
+ ".so.", major_version, NULL);
+ }
+ else if (binary_format == CHAZ_CC_BINFMT_PE) {
+ string = chaz_Util_join("", "-shared -Wl,--out-implib,lib",
+ basename, "-", major_version, ".dll.a",
+ NULL);
}
}
else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) {
- string = "-G";
+ string = chaz_Util_join("", "-G -h lib", basename, ".so.",
+ major_version, NULL);
}
else {
chaz_Util_die("Don't know how to link a shared library with '%s'",
chaz_CC_get_cc());
}
- chaz_CFlags_append(flags, string);
-}
-void
-chaz_CFlags_set_shared_library_version(chaz_CFlags *flags, chaz_Lib *lib) {
- if (flags->style == CHAZ_CFLAGS_STYLE_GNU) {
- int binary_format = chaz_CC_binary_format();
-
- if (binary_format == CHAZ_CC_BINFMT_MACHO) {
- const char *version = chaz_Lib_get_version(lib);
- char *string
- = chaz_Util_join(" ", "-current_version", version, NULL);
- chaz_CFlags_append(flags, string);
- free(string);
- }
- else if (binary_format == CHAZ_CC_BINFMT_ELF) {
- char *soname = chaz_Lib_major_version_filename(lib);
- char *string = chaz_Util_join("", "-Wl,-soname,", soname, NULL);
- chaz_CFlags_append(flags, string);
- free(string);
- free(soname);
- }
- }
- else if (flags->style == CHAZ_CFLAGS_STYLE_SUN_C) {
- char *soname = chaz_Lib_major_version_filename(lib);
- char *string = chaz_Util_join(" ", "-h", soname, NULL);
+ if (string) {
chaz_CFlags_append(flags, string);
free(string);
- free(soname);
}
}
@@ -333,20 +321,22 @@
}
void
-chaz_CFlags_add_library(chaz_CFlags *flags, chaz_Lib *lib) {
+chaz_CFlags_add_shared_lib(chaz_CFlags *flags, const char *dir,
+ const char *basename, const char *major_version) {
+ int binfmt = chaz_CC_binary_format();
char *filename;
- if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
- filename = chaz_Lib_implib_filename(lib);
+ if (binfmt == CHAZ_CC_BINFMT_PE) {
+ filename = chaz_CC_import_lib_filename(dir, basename, major_version);
}
else {
- filename = chaz_Lib_filename(lib);
+ filename = chaz_CC_shared_lib_filename(dir, basename, major_version);
}
chaz_CFlags_append(flags, filename);
free(filename);
}
void
-chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library) {
+chaz_CFlags_add_external_lib(chaz_CFlags *flags, const char *library) {
char *string;
if (flags->style == CHAZ_CFLAGS_STYLE_MSVC) {
string = chaz_Util_join("", library, ".lib", NULL);
diff --git a/src/Charmonizer/Core/CFlags.h b/src/Charmonizer/Core/CFlags.h
index 901eb45..ec699df 100644
--- a/src/Charmonizer/Core/CFlags.h
+++ b/src/Charmonizer/Core/CFlags.h
@@ -24,8 +24,6 @@
extern "C" {
#endif
-#include "Charmonizer/Core/Library.h"
-
#define CHAZ_CFLAGS_STYLE_POSIX 1
#define CHAZ_CFLAGS_STYLE_GNU 2
#define CHAZ_CFLAGS_STYLE_MSVC 3
@@ -77,10 +75,9 @@
chaz_CFlags_hide_symbols(chaz_CFlags *flags);
void
-chaz_CFlags_link_shared_library(chaz_CFlags *flags);
-
-void
-chaz_CFlags_set_shared_library_version(chaz_CFlags *flags, chaz_Lib *lib);
+chaz_CFlags_link_shared_library(chaz_CFlags *flags, const char *basename,
+ const char *version,
+ const char *major_version);
void
chaz_CFlags_set_link_output(chaz_CFlags *flags, const char *filename);
@@ -89,10 +86,11 @@
chaz_CFlags_add_library_path(chaz_CFlags *flags, const char *directory);
void
-chaz_CFlags_add_library(chaz_CFlags *flags, chaz_Lib *lib);
+chaz_CFlags_add_shared_lib(chaz_CFlags *flags, const char *dir,
+ const char *basename, const char *major_version);
void
-chaz_CFlags_add_external_library(chaz_CFlags *flags, const char *library);
+chaz_CFlags_add_external_lib(chaz_CFlags *flags, const char *library);
void
chaz_CFlags_enable_code_coverage(chaz_CFlags *flags);
diff --git a/src/Charmonizer/Core/Compiler.c b/src/Charmonizer/Core/Compiler.c
index dd4fa6c..83177f2 100644
--- a/src/Charmonizer/Core/Compiler.c
+++ b/src/Charmonizer/Core/Compiler.c
@@ -37,6 +37,13 @@
static void
chaz_CC_detect_known_compilers(void);
+/** Build a library filename from its components.
+ */
+static char*
+chaz_CC_build_lib_filename(const char *dir, const char *prefix,
+ const char *basename, const char *version,
+ const char *ext);
+
/* Temporary files. */
#define CHAZ_CC_TRY_SOURCE_PATH "_charmonizer_try.c"
#define CHAZ_CC_TRY_BASENAME "_charmonizer_try"
@@ -75,7 +82,6 @@
chaz_CC_init(const char *compiler_command, const char *compiler_flags) {
const char *code = "int main() { return 0; }\n";
int compile_succeeded = 0;
- int retval = -1;
if (chaz_Util_verbosity) { printf("Creating compiler object...\n"); }
@@ -566,7 +572,8 @@
/* TODO: Write `objects` to a temporary file in order to avoid
* exceeding line length limits. */
char *out = chaz_Util_join("", "/OUT:", target, NULL);
- char *command = chaz_Util_join(" ", "lib", "/NOLOGO", out, NULL);
+ char *command = chaz_Util_join(" ", "lib", "/NOLOGO", objects, out,
+ NULL);
free(out);
return command;
}
@@ -583,3 +590,85 @@
return chaz_Util_join(" ", "ranlib", target, NULL);
}
+char*
+chaz_CC_shared_lib_filename(const char *dir, const char *basename,
+ const char *version) {
+ /* Cygwin uses a "cyg" prefix for shared libraries. */
+ const char *prefix = chaz_CC_msvc_version_num()
+ ? ""
+ : chaz_CC_is_cygwin() ? "cyg" : "lib";
+ return chaz_CC_build_lib_filename(dir, prefix, basename, version,
+ chaz_CC.shared_lib_ext);
+}
+
+char*
+chaz_CC_import_lib_filename(const char *dir, const char *basename,
+ const char *version) {
+ const char *prefix = chaz_CC_msvc_version_num() ? "" : "lib";
+ return chaz_CC_build_lib_filename(dir, prefix, basename, version,
+ chaz_CC.import_lib_ext);
+}
+
+char*
+chaz_CC_export_filename(const char *dir, const char *basename,
+ const char *version) {
+ /* Only for MSVC. */
+ return chaz_CC_build_lib_filename(dir, "", basename, version, ".exp");
+}
+
+static char*
+chaz_CC_build_lib_filename(const char *dir, const char *prefix,
+ const char *basename, const char *version,
+ const char *ext) {
+ char *suffix;
+ char *retval;
+
+ if (version == NULL) {
+ suffix = chaz_Util_strdup(ext);
+ }
+ else {
+ int binary_format = chaz_CC_binary_format();
+
+ if (binary_format == CHAZ_CC_BINFMT_PE) {
+ suffix = chaz_Util_join("", "-", version, ext, NULL);
+ }
+ else if (binary_format == CHAZ_CC_BINFMT_MACHO) {
+ suffix = chaz_Util_join("", ".", version, ext, NULL);
+ }
+ else if (binary_format == CHAZ_CC_BINFMT_ELF) {
+ suffix = chaz_Util_join("", ext, ".", version, NULL);
+ }
+ else {
+ chaz_Util_die("Unsupported binary format");
+ return NULL;
+ }
+ }
+
+ if (dir == NULL || strcmp(dir, ".") == 0) {
+ retval = chaz_Util_join("", prefix, basename, suffix, NULL);
+ }
+ else {
+ const char *dir_sep = chaz_OS_dir_sep();
+ retval = chaz_Util_join("", dir, dir_sep, prefix, basename, suffix,
+ NULL);
+ }
+
+ free(suffix);
+ return retval;
+}
+
+char*
+chaz_CC_static_lib_filename(const char *dir, const char *basename) {
+ const char *prefix = chaz_CC_msvc_version_num() ? "" : "lib";
+
+ if (dir == NULL || strcmp(dir, ".") == 0) {
+ return chaz_Util_join("", prefix, basename, chaz_CC.static_lib_ext,
+ NULL);
+ }
+ else {
+ const char *dir_sep = chaz_OS_dir_sep();
+ return chaz_Util_join("", dir, dir_sep, prefix, basename,
+ chaz_CC.static_lib_ext, NULL);
+ }
+}
+
diff --git a/src/Charmonizer/Core/Compiler.h b/src/Charmonizer/Core/Compiler.h
index 6361af7..8190123 100644
--- a/src/Charmonizer/Core/Compiler.h
+++ b/src/Charmonizer/Core/Compiler.h
@@ -169,6 +169,44 @@
char*
chaz_CC_format_ranlib_command(const char *target);
+/** Returns the filename for a shared library.
+ *
+ * @param dir The target directory or NULL for the current directory.
+ * @param basename The name of the library without prefix and extension.
+ * @param version The library version.
+ */
+char*
+chaz_CC_shared_lib_filename(const char *dir, const char *basename,
+ const char *version);
+
+/** Returns the filename for an import library.
+ *
+ * @param dir The target directory or NULL for the current directory.
+ * @param basename The name of the library without prefix and extension.
+ * @param version The library version.
+ */
+char*
+chaz_CC_import_lib_filename(const char *dir, const char *basename,
+ const char *version);
+
+/** Returns the filename for an MSVC export file.
+ *
+ * @param dir The target directory or NULL for the current directory.
+ * @param basename The name of the library without prefix and extension.
+ * @param version The library version.
+ */
+char*
+chaz_CC_export_filename(const char *dir, const char *basename,
+ const char *version);
+
+/** Returns the filename for a static library.
+ *
+ * @param dir The target directory or NULL for the current directory.
+ * @param basename The name of the library without prefix and extension.
+ */
+char*
+chaz_CC_static_lib_filename(const char *dir, const char *basename);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/Charmonizer/Core/Library.c b/src/Charmonizer/Core/Library.c
deleted file mode 100644
index d1e0cb6..0000000
--- a/src/Charmonizer/Core/Library.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include "Charmonizer/Core/Library.h"
-#include "Charmonizer/Core/Compiler.h"
-#include "Charmonizer/Core/Util.h"
-#include "Charmonizer/Core/OperatingSystem.h"
-
-struct chaz_Lib {
- char *name;
- char *version;
- char *major_version;
- int is_static;
- int is_shared;
-};
-
-static char*
-S_build_filename(chaz_Lib *lib, const char *version, const char *ext);
-
-static const char*
-S_get_prefix(chaz_Lib *lib);
-
-chaz_Lib*
-chaz_Lib_new_shared(const char *name, const char *version,
- const char *major_version) {
- chaz_Lib *lib = (chaz_Lib*)malloc(sizeof(chaz_Lib));
- lib->name = chaz_Util_strdup(name);
- lib->version = chaz_Util_strdup(version);
- lib->major_version = chaz_Util_strdup(major_version);
- lib->is_shared = 1;
- lib->is_static = 0;
- return lib;
-}
-
-chaz_Lib*
-chaz_Lib_new_static(const char *name) {
- chaz_Lib *lib = (chaz_Lib*)malloc(sizeof(chaz_Lib));
- lib->name = chaz_Util_strdup(name);
- lib->version = NULL;
- lib->major_version = NULL;
- lib->is_shared = 0;
- lib->is_static = 1;
- return lib;
-}
-
-void
-chaz_Lib_destroy(chaz_Lib *lib) {
- free(lib->name);
- free(lib->version);
- free(lib->major_version);
- free(lib);
-}
-
-const char*
-chaz_Lib_get_name(chaz_Lib *lib) {
- return lib->name;
-}
-
-const char*
-chaz_Lib_get_version(chaz_Lib *lib) {
- return lib->version;
-}
-
-const char*
-chaz_Lib_get_major_version(chaz_Lib *lib) {
- return lib->major_version;
-}
-
-int
-chaz_Lib_is_shared (chaz_Lib *lib) {
- return lib->is_shared;
-}
-
-int
-chaz_Lib_is_static (chaz_Lib *lib) {
- return lib->is_static;
-}
-
-char*
-chaz_Lib_filename(chaz_Lib *lib) {
- if (lib->is_static) {
- return chaz_Lib_no_version_filename(lib);
- }
- else {
- const char *ext = chaz_CC_shared_lib_ext();
- if (chaz_CC_binary_format() == CHAZ_CC_BINFMT_PE) {
- return S_build_filename(lib, lib->major_version, ext);
- }
- else {
- return S_build_filename(lib, lib->version, ext);
- }
- }
-}
-
-char*
-chaz_Lib_major_version_filename(chaz_Lib *lib) {
- if (lib->is_static) {
- return chaz_Lib_no_version_filename(lib);
- }
- else {
- const char *ext = chaz_CC_shared_lib_ext();
- return S_build_filename(lib, lib->major_version, ext);
- }
-}
-
-char*
-chaz_Lib_no_version_filename(chaz_Lib *lib) {
- const char *prefix = S_get_prefix(lib);
- const char *ext = lib->is_shared
- ? chaz_CC_shared_lib_ext()
- : chaz_CC_static_lib_ext();
- return chaz_Util_join("", prefix, lib->name, ext, NULL);
-}
-
-char*
-chaz_Lib_implib_filename(chaz_Lib *lib) {
- const char *ext = chaz_CC_import_lib_ext();
- return S_build_filename(lib, lib->major_version, ext);
-}
-
-char*
-chaz_Lib_export_filename(chaz_Lib *lib) {
- return S_build_filename(lib, lib->major_version, ".exp");
-}
-
-static char*
-S_build_filename(chaz_Lib *lib, const char *version, const char *ext) {
- const char *prefix = S_get_prefix(lib);
- int binary_format = chaz_CC_binary_format();
-
- if (binary_format == CHAZ_CC_BINFMT_PE) {
- return chaz_Util_join("", prefix, lib->name, "-", version, ext, NULL);
- }
- else if (binary_format == CHAZ_CC_BINFMT_MACHO) {
- return chaz_Util_join("", prefix, lib->name, ".", version, ext, NULL);
- }
- else if (binary_format == CHAZ_CC_BINFMT_ELF) {
- return chaz_Util_join("", prefix, lib->name, ext, ".", version, NULL);
- }
- else {
- chaz_Util_die("Unsupported binary format");
- return NULL;
- }
-}
-
-static const char*
-S_get_prefix(chaz_Lib *lib) {
- if (chaz_CC_msvc_version_num()) {
- return "";
- }
- else if (chaz_CC_is_cygwin()) {
- return lib->is_static ? "lib" : "cyg";
- }
- else {
- return "lib";
- }
-}
-
-
diff --git a/src/Charmonizer/Core/Library.h b/src/Charmonizer/Core/Library.h
deleted file mode 100644
index 80fff83..0000000
--- a/src/Charmonizer/Core/Library.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Charmonizer/Core/Library.h
- */
-
-#ifndef H_CHAZ_LIB
-#define H_CHAZ_LIB
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct chaz_Lib chaz_Lib;
-
-chaz_Lib*
-chaz_Lib_new_shared(const char *name, const char *version,
- const char *major_version);
-
-chaz_Lib*
-chaz_Lib_new_static(const char *name);
-
-void
-chaz_Lib_destroy(chaz_Lib *flags);
-
-const char*
-chaz_Lib_get_name(chaz_Lib *lib);
-
-const char*
-chaz_Lib_get_version(chaz_Lib *lib);
-
-const char*
-chaz_Lib_get_major_version(chaz_Lib *lib);
-
-int
-chaz_Lib_is_shared(chaz_Lib *lib);
-
-int
-chaz_Lib_is_static(chaz_Lib *lib);
-
-char*
-chaz_Lib_filename(chaz_Lib *lib);
-
-char*
-chaz_Lib_major_version_filename(chaz_Lib *lib);
-
-char*
-chaz_Lib_no_version_filename(chaz_Lib *lib);
-
-char*
-chaz_Lib_implib_filename(chaz_Lib *lib);
-
-char*
-chaz_Lib_export_filename(chaz_Lib *lib);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* H_CHAZ_LIB */
-
-
diff --git a/src/Charmonizer/Core/Make.c b/src/Charmonizer/Core/Make.c
index 8e8699b..23350f8 100644
--- a/src/Charmonizer/Core/Make.c
+++ b/src/Charmonizer/Core/Make.c
@@ -18,10 +18,15 @@
#include <stdlib.h>
#include <string.h>
#include "Charmonizer/Core/Make.h"
+#include "Charmonizer/Core/CFlags.h"
#include "Charmonizer/Core/Compiler.h"
#include "Charmonizer/Core/OperatingSystem.h"
#include "Charmonizer/Core/Util.h"
+#define CHAZ_MAKEBINARY_EXE 1
+#define CHAZ_MAKEBINARY_STATIC_LIB 2
+#define CHAZ_MAKEBINARY_SHARED_LIB 3
+
struct chaz_MakeVar {
char *name;
char *value;
@@ -34,13 +39,34 @@
char *commands;
};
+struct chaz_MakeBinary {
+ int type;
+ char *target_dir;
+ char *basename;
+ char *version;
+ char *major_version;
+ char **sources; /* List of all sources. */
+ size_t num_sources;
+ char **single_sources; /* Only sources from add_src_file. */
+ size_t num_single_sources;
+ char **dirs;
+ size_t num_dirs;
+ chaz_MakeVar *obj_var; /* Owned by MakeFile. */
+ char *dollar_var;
+ chaz_MakeRule *rule; /* Not added to MakeFile, owned by MakeBinary. */
+ chaz_CFlags *compile_flags;
+ chaz_CFlags *link_flags;
+};
+
struct chaz_MakeFile {
- chaz_MakeVar **vars;
- size_t num_vars;
- chaz_MakeRule **rules;
- size_t num_rules;
- chaz_MakeRule *clean;
- chaz_MakeRule *distclean;
+ chaz_MakeVar **vars;
+ size_t num_vars;
+ chaz_MakeRule **rules;
+ size_t num_rules;
+ chaz_MakeRule *clean;
+ chaz_MakeRule *distclean;
+ chaz_MakeBinary **binaries;
+ size_t num_binaries;
};
/* Static vars. */
@@ -69,6 +95,31 @@
static int
chaz_Make_audition(const char *make);
+static void
+chaz_MakeFile_finish_exe(chaz_MakeFile *self, chaz_MakeBinary *binary);
+
+static void
+chaz_MakeFile_finish_shared_lib(chaz_MakeFile *self, chaz_MakeBinary *binary);
+
+static void
+chaz_MakeFile_finish_static_lib(chaz_MakeFile *self, chaz_MakeBinary *binary);
+
+static chaz_MakeBinary*
+chaz_MakeFile_add_binary(chaz_MakeFile *self, int type, const char *dir,
+ const char *basename, const char *target);
+
+static void
+chaz_MakeFile_write_binary_rules(chaz_MakeFile *self, chaz_MakeBinary *binary,
+ FILE *out);
+
+static void
+chaz_MakeFile_write_object_rules(char **sources, const char *command,
+ FILE *out);
+
+static void
+chaz_MakeFile_write_pattern_rules(char **dirs, const char *command,
+ FILE *out);
+
static chaz_MakeRule*
S_new_rule(const char *target, const char *prereq);
@@ -78,19 +129,48 @@
static void
S_write_rule(chaz_MakeRule *rule, FILE *out);
+static void
+chaz_MakeBinary_destroy(chaz_MakeBinary *self);
+
+static void
+chaz_MakeBinary_list_files_callback(const char *dir, char *file,
+ void *context);
+static void
+chaz_MakeBinary_do_add_src_file(chaz_MakeBinary *self, const char *path);
+
+/** Return the path to the object file for a source file.
+ *
+ * @param path The path to the source file.
+ */
+static char*
+chaz_MakeBinary_obj_path(const char *src_path);
+
void
chaz_Make_init(const char *make_command) {
chaz_Make.shell_type = chaz_OS_shell_type();
if (make_command) {
if (!chaz_Make_detect(make_command, NULL)) {
- chaz_Util_warn("Make utility '%s' doesn't appear to work");
+ chaz_Util_warn("Make utility '%s' doesn't appear to work",
+ make_command);
}
}
else {
- if (!chaz_Make_detect("make", "gmake", "nmake", "dmake",
- "mingw32-make", "mingw64-make", NULL)
- ) {
+ int succeeded = 0;
+
+ /* mingw32-make seems to try to run commands under both cmd.exe
+ * and sh.exe. Not sure about dmake.
+ */
+ if (chaz_Make.shell_type == CHAZ_OS_POSIX) {
+ succeeded = chaz_Make_detect("make", "gmake", "dmake",
+ "mingw32-make", NULL);
+ }
+ else if (chaz_Make.shell_type = CHAZ_OS_CMD_EXE) {
+ succeeded = chaz_Make_detect("nmake", "dmake", "mingw32-make",
+ NULL);
+ }
+
+ if (!succeeded) {
chaz_Util_warn("No working make utility found");
}
else if (chaz_Util_verbosity) {
@@ -119,7 +199,7 @@
va_list args;
const char *candidate;
int found = 0;
- const char makefile_content[] = "foo:\n\techo foo\\^bar\n";
+ const char makefile_content[] = "foo:\n\t@echo 643490c943525d19\n";
chaz_Util_write_file("_charm_Makefile", makefile_content);
/* Audition candidates. */
@@ -145,15 +225,8 @@
if (chaz_Util_can_open_file("_charm_foo")) {
size_t len;
char *content = chaz_Util_slurp_file("_charm_foo", &len);
- if (NULL != strstr(content, "foo\\bar")) {
- if (chaz_Make.shell_type == CHAZ_OS_CMD_EXE) {
- succeeded = 1;
- }
- }
- else if (NULL != strstr(content, "foo^bar")) {
- if (chaz_Make.shell_type == CHAZ_OS_POSIX) {
- succeeded = 1;
- }
+ if (content != NULL && strstr(content, "643490c943525d19") != NULL) {
+ succeeded = 1;
}
free(content);
}
@@ -169,51 +242,52 @@
chaz_MakeFile*
chaz_MakeFile_new() {
- chaz_MakeFile *makefile = (chaz_MakeFile*)malloc(sizeof(chaz_MakeFile));
+ chaz_MakeFile *self = (chaz_MakeFile*)calloc(1, sizeof(chaz_MakeFile));
const char *exe_ext = chaz_CC_exe_ext();
const char *obj_ext = chaz_CC_obj_ext();
char *generated;
- makefile->vars = (chaz_MakeVar**)malloc(sizeof(chaz_MakeVar*));
- makefile->vars[0] = NULL;
- makefile->num_vars = 0;
+ self->vars = (chaz_MakeVar**)calloc(1, sizeof(chaz_MakeVar*));
+ self->rules = (chaz_MakeRule**)calloc(1, sizeof(chaz_MakeRule*));
+ self->binaries = (chaz_MakeBinary**)calloc(1, sizeof(chaz_MakeBinary*));
- makefile->rules = (chaz_MakeRule**)malloc(sizeof(chaz_MakeRule*));
- makefile->rules[0] = NULL;
- makefile->num_rules = 0;
-
- makefile->clean = S_new_rule("clean", NULL);
- makefile->distclean = S_new_rule("distclean", "clean");
+ self->clean = S_new_rule("clean", NULL);
+ self->distclean = S_new_rule("distclean", "clean");
generated = chaz_Util_join("", "charmonizer", exe_ext, " charmonizer",
obj_ext, " charmony.h Makefile", NULL);
- chaz_MakeRule_add_rm_command(makefile->distclean, generated);
+ chaz_MakeRule_add_rm_command(self->distclean, generated);
free(generated);
- return makefile;
+ return self;
}
void
-chaz_MakeFile_destroy(chaz_MakeFile *makefile) {
+chaz_MakeFile_destroy(chaz_MakeFile *self) {
size_t i;
- for (i = 0; makefile->vars[i]; i++) {
- chaz_MakeVar *var = makefile->vars[i];
+ for (i = 0; self->vars[i]; i++) {
+ chaz_MakeVar *var = self->vars[i];
free(var->name);
free(var->value);
free(var);
}
- free(makefile->vars);
+ free(self->vars);
- for (i = 0; makefile->rules[i]; i++) {
- S_destroy_rule(makefile->rules[i]);
+ for (i = 0; self->rules[i]; i++) {
+ S_destroy_rule(self->rules[i]);
}
- free(makefile->rules);
+ free(self->rules);
- S_destroy_rule(makefile->clean);
- S_destroy_rule(makefile->distclean);
+ for (i = 0; self->binaries[i]; i++) {
+ chaz_MakeBinary_destroy(self->binaries[i]);
+ }
+ free(self->binaries);
- free(makefile);
+ S_destroy_rule(self->clean);
+ S_destroy_rule(self->distclean);
+
+ free(self);
}
chaz_MakeVar*
@@ -266,196 +340,249 @@
return makefile->distclean;
}
-chaz_MakeRule*
-chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
- const char *sources, chaz_CFlags *link_flags) {
- chaz_CFlags *local_flags = chaz_CC_new_cflags();
- const char *link = chaz_CC_link_command();
- const char *link_flags_string = "";
- const char *local_flags_string;
- chaz_MakeRule *rule;
- char *command;
+chaz_MakeBinary*
+chaz_MakeFile_add_exe(chaz_MakeFile *self, const char *dir,
+ const char *basename) {
+ const char *exe_ext = chaz_CC_exe_ext();
+ char *target;
+ chaz_MakeBinary *binary;
- rule = chaz_MakeFile_add_rule(makefile, exe, sources);
-
- if (link_flags) {
- link_flags_string = chaz_CFlags_get_string(link_flags);
+ if (dir == NULL || strcmp(dir, ".") == 0) {
+ target = chaz_Util_join("", basename, exe_ext, NULL);
}
- if (chaz_CC_msvc_version_num()) {
- chaz_CFlags_append(local_flags, "/nologo");
+ else {
+ const char *dir_sep = chaz_OS_dir_sep();
+ target = chaz_Util_join("", dir, dir_sep, basename, exe_ext, NULL);
}
- chaz_CFlags_set_link_output(local_flags, exe);
- local_flags_string = chaz_CFlags_get_string(local_flags);
- command = chaz_Util_join(" ", link, sources, link_flags_string,
- local_flags_string, NULL);
- chaz_MakeRule_add_command(rule, command);
- chaz_MakeRule_add_rm_command(makefile->clean, exe);
+ binary = chaz_MakeFile_add_binary(self, CHAZ_MAKEBINARY_EXE, dir, basename,
+ target);
- chaz_CFlags_destroy(local_flags);
- free(command);
- return rule;
+ free(target);
+ return binary;
}
-chaz_MakeRule*
-chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
- const char *sources, chaz_CFlags *cflags) {
- chaz_CFlags *local_flags = chaz_CC_new_cflags();
- const char *cc = chaz_CC_get_cc();
- const char *cflags_string = "";
- const char *local_flags_string;
- chaz_MakeRule *rule;
- char *command;
-
- rule = chaz_MakeFile_add_rule(makefile, exe, sources);
-
- if (cflags) {
- cflags_string = chaz_CFlags_get_string(cflags);
- }
- if (chaz_CC_msvc_version_num()) {
- chaz_CFlags_append(local_flags, "/nologo");
- }
- chaz_CFlags_set_output_exe(local_flags, exe);
- local_flags_string = chaz_CFlags_get_string(local_flags);
- command = chaz_Util_join(" ", cc, sources, cflags_string,
- local_flags_string, NULL);
- chaz_MakeRule_add_command(rule, command);
-
- chaz_MakeRule_add_rm_command(makefile->clean, exe);
- /* TODO: Clean .obj file on Windows. */
-
- chaz_CFlags_destroy(local_flags);
- free(command);
- return rule;
-}
-
-chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
- const char *sources, chaz_CFlags *link_flags) {
- chaz_CFlags *local_flags = chaz_CC_new_cflags();
+void
+chaz_MakeFile_finish_exe(chaz_MakeFile *self, chaz_MakeBinary *binary) {
const char *link = chaz_CC_link_command();
- const char *link_flags_string = "";
- const char *local_flags_string;
- int binfmt = chaz_CC_binary_format();
- chaz_MakeRule *rule;
- char *filename;
+ const char *link_flags_string;
char *command;
- filename = chaz_Lib_filename(lib);
- rule = chaz_MakeFile_add_rule(makefile, filename, sources);
+ (void)self;
- if (link_flags) {
- link_flags_string = chaz_CFlags_get_string(link_flags);
+ /* This is destructive but shouldn't be a problem since a Makefile
+ * is only written once.
+ */
+ chaz_CFlags_set_link_output(binary->link_flags, "$@");
+ link_flags_string = chaz_CFlags_get_string(binary->link_flags);
+
+ /* Objects in dollar var must come before flags since flags may
+ * contain libraries.
+ */
+ command = chaz_Util_join(" ", link, binary->dollar_var, link_flags_string,
+ NULL);
+ chaz_MakeRule_add_command(binary->rule, command);
+ free(command);
+}
+
+chaz_MakeBinary*
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *self, const char *dir,
+ const char *basename, const char *version,
+ const char *major_version) {
+ int binary_format = chaz_CC_binary_format();
+ char *target;
+ chaz_MakeBinary *binary;
+
+ if (binary_format == CHAZ_CC_BINFMT_PE) {
+ target = chaz_CC_shared_lib_filename(dir, basename, major_version);
+ }
+ else {
+ target = chaz_CC_shared_lib_filename(dir, basename, version);
}
- if (chaz_CC_msvc_version_num()) {
- chaz_CFlags_append(local_flags, "/nologo");
- }
- chaz_CFlags_link_shared_library(local_flags);
+ binary = chaz_MakeFile_add_binary(self, CHAZ_MAKEBINARY_SHARED_LIB, dir,
+ basename, target);
+ binary->version = chaz_Util_strdup(version);
+ binary->major_version = chaz_Util_strdup(major_version);
+
+ chaz_CFlags_compile_shared_library(binary->compile_flags);
+ chaz_CFlags_link_shared_library(binary->link_flags, basename, version,
+ major_version);
+
+ free(target);
+ return binary;
+}
+
+void
+chaz_MakeFile_finish_shared_lib(chaz_MakeFile *self, chaz_MakeBinary *binary) {
+ const char *link = chaz_CC_link_command();
+ const char *link_flags_string;
+ int binfmt = chaz_CC_binary_format();
+ char *no_v_name
+ = chaz_CC_shared_lib_filename(binary->target_dir, binary->basename,
+ NULL);
+ char *major_v_name
+ = chaz_CC_shared_lib_filename(binary->target_dir, binary->basename,
+ binary->major_version);
+ char *command;
+
if (binfmt == CHAZ_CC_BINFMT_MACHO) {
- /* Set temporary install name with full path on Darwin. */
const char *dir_sep = chaz_OS_dir_sep();
- char *major_v_name = chaz_Lib_major_version_filename(lib);
- char *install_name = chaz_Util_join("", "-install_name $(CURDIR)",
- dir_sep, major_v_name, NULL);
- chaz_CFlags_append(local_flags, install_name);
- free(major_v_name);
+ char *install_name;
+
+ /* Set temporary install name with full path on Darwin. */
+ install_name = chaz_Util_join("", "-install_name $(CURDIR)", dir_sep,
+ major_v_name, NULL);
+ chaz_CFlags_append(binary->link_flags, install_name);
free(install_name);
}
- chaz_CFlags_set_shared_library_version(local_flags, lib);
- chaz_CFlags_set_link_output(local_flags, filename);
- local_flags_string = chaz_CFlags_get_string(local_flags);
- command = chaz_Util_join(" ", link, sources, link_flags_string,
- local_flags_string, NULL);
- chaz_MakeRule_add_command(rule, command);
+ chaz_CFlags_set_link_output(binary->link_flags, "$@");
+ link_flags_string = chaz_CFlags_get_string(binary->link_flags);
+
+ command = chaz_Util_join(" ", link, binary->dollar_var, link_flags_string,
+ NULL);
+ chaz_MakeRule_add_command(binary->rule, command);
free(command);
- chaz_MakeRule_add_rm_command(makefile->clean, filename);
-
/* Add symlinks. */
if (binfmt == CHAZ_CC_BINFMT_ELF || binfmt == CHAZ_CC_BINFMT_MACHO) {
- char *major_v_name = chaz_Lib_major_version_filename(lib);
- char *no_v_name = chaz_Lib_no_version_filename(lib);
-
- command = chaz_Util_join(" ", "ln -sf", filename, major_v_name, NULL);
- chaz_MakeRule_add_command(rule, command);
+ command = chaz_Util_join(" ", "ln -sf", binary->rule->targets,
+ major_v_name, NULL);
+ chaz_MakeRule_add_command(binary->rule, command);
free(command);
if (binfmt == CHAZ_CC_BINFMT_MACHO) {
- command = chaz_Util_join(" ", "ln -sf", filename, no_v_name,
- NULL);
+ command = chaz_Util_join(" ", "ln -sf", binary->rule->targets,
+ no_v_name, NULL);
}
else {
command = chaz_Util_join(" ", "ln -sf", major_v_name, no_v_name,
NULL);
}
- chaz_MakeRule_add_command(rule, command);
+ chaz_MakeRule_add_command(binary->rule, command);
free(command);
- chaz_MakeRule_add_rm_command(makefile->clean, major_v_name);
- chaz_MakeRule_add_rm_command(makefile->clean, no_v_name);
+ chaz_MakeRule_add_rm_command(self->clean, major_v_name);
+ chaz_MakeRule_add_rm_command(self->clean, no_v_name);
+ }
- free(major_v_name);
- free(no_v_name);
+ if (binfmt == CHAZ_CC_BINFMT_PE) {
+ /* Remove import library. */
+ char *filename
+ = chaz_CC_import_lib_filename(binary->target_dir, binary->basename,
+ binary->major_version);
+ chaz_MakeRule_add_rm_command(self->clean, filename);
+ free(filename);
}
if (chaz_CC_msvc_version_num()) {
- /* Remove import library and export file under MSVC. */
- char *lib_filename = chaz_Lib_implib_filename(lib);
- char *exp_filename = chaz_Lib_export_filename(lib);
- chaz_MakeRule_add_rm_command(makefile->clean, lib_filename);
- chaz_MakeRule_add_rm_command(makefile->clean, exp_filename);
- free(lib_filename);
- free(exp_filename);
+ /* Remove export file. */
+ char *filename
+ = chaz_CC_export_filename(binary->target_dir, binary->basename,
+ binary->major_version);
+ chaz_MakeRule_add_rm_command(self->clean, filename);
+ free(filename);
}
- chaz_CFlags_destroy(local_flags);
- free(filename);
- return rule;
+ free(major_v_name);
+ free(no_v_name);
}
-chaz_MakeRule*
-chaz_MakeFile_add_static_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
- const char *objects) {
- chaz_MakeRule *rule;
- char *filename;
- char *command;
+chaz_MakeBinary*
+chaz_MakeFile_add_static_lib(chaz_MakeFile *self, const char *dir,
+ const char *basename) {
+ char *target = chaz_CC_static_lib_filename(dir, basename);
+ chaz_MakeBinary *binary
+ = chaz_MakeFile_add_binary(self, CHAZ_MAKEBINARY_STATIC_LIB, dir,
+ basename, target);
- filename = chaz_Lib_filename(lib);
- rule = chaz_MakeFile_add_rule(makefile, filename, objects);
- command = chaz_CC_format_archiver_command(filename, objects);
- chaz_MakeRule_add_command(rule, command);
+ free(target);
+ return binary;
+}
+
+static void
+chaz_MakeFile_finish_static_lib(chaz_MakeFile *self, chaz_MakeBinary *binary) {
+ char *command;
+
+ (void)self;
+
+ command = chaz_CC_format_archiver_command("$@", binary->dollar_var);
+ chaz_MakeRule_add_command(binary->rule, command);
free(command);
- command = chaz_CC_format_ranlib_command(filename);
+
+ command = chaz_CC_format_ranlib_command("$@");
if (command) {
- chaz_MakeRule_add_command(rule, command);
+ chaz_MakeRule_add_command(binary->rule, command);
free(command);
}
- chaz_MakeRule_add_rm_command(makefile->clean, filename);
-
- free(filename);
- return rule;
}
-chaz_MakeRule*
+static chaz_MakeBinary*
+chaz_MakeFile_add_binary(chaz_MakeFile *self, int type, const char *dir,
+ const char *basename, const char *target) {
+ chaz_MakeBinary *binary
+ = (chaz_MakeBinary*)calloc(1, sizeof(chaz_MakeBinary));
+ const char *suffix;
+ char *uc_basename = chaz_Util_strdup(basename);
+ char *binary_var_name;
+ char *obj_var_name;
+ char *dollar_var;
+ size_t i;
+ size_t num_binaries;
+ size_t alloc_size;
+ chaz_MakeBinary **binaries;
+
+ switch (type) {
+ case CHAZ_MAKEBINARY_EXE: suffix = "EXE"; break;
+ case CHAZ_MAKEBINARY_STATIC_LIB: suffix = "STATIC_LIB"; break;
+ case CHAZ_MAKEBINARY_SHARED_LIB: suffix = "SHARED_LIB"; break;
+ default:
+ chaz_Util_die("Unknown binary type %d", type);
+ return NULL;
+ }
+
+ for (i = 0; uc_basename[i] != '\0'; i++) {
+ uc_basename[i] = toupper((unsigned char)uc_basename[i]);
+ }
+
+ binary_var_name = chaz_Util_join("_", uc_basename, suffix, NULL);
+ obj_var_name = chaz_Util_join("_", uc_basename, suffix, "OBJS", NULL);
+ dollar_var = chaz_Util_join("", "$(", obj_var_name, ")", NULL);
+
+ chaz_MakeFile_add_var(self, binary_var_name, target);
+
+ binary->type = type;
+ binary->target_dir = dir ? chaz_Util_strdup(dir) : NULL;
+ binary->basename = chaz_Util_strdup(basename);
+ binary->obj_var = chaz_MakeFile_add_var(self, obj_var_name, NULL);
+ binary->dollar_var = dollar_var;
+ binary->rule = S_new_rule(target, dollar_var);
+ binary->sources = (char**)calloc(1, sizeof(char*));
+ binary->single_sources = (char**)calloc(1, sizeof(char*));
+ binary->dirs = (char**)calloc(1, sizeof(char*));
+ binary->compile_flags = chaz_CC_new_cflags();
+ binary->link_flags = chaz_CC_new_cflags();
+
+ num_binaries = self->num_binaries;
+ alloc_size = (num_binaries + 2) * sizeof(chaz_MakeBinary*);
+ binaries = (chaz_MakeBinary**)realloc(self->binaries, alloc_size);
+ binaries[num_binaries] = binary;
+ binaries[num_binaries+1] = NULL;
+ self->binaries = binaries;
+ self->num_binaries = num_binaries + 1;
+
+ free(uc_basename);
+ free(obj_var_name);
+ free(binary_var_name);
+ return binary;
+}
+
+chaz_MakeBinary*
chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir) {
- chaz_CFlags *cflags = chaz_CC_new_cflags();
- chaz_MakeRule *rule;
- const char *dir_sep = chaz_OS_dir_sep();
- const char *exe_ext = chaz_CC_exe_ext();
- char *lemon_exe = chaz_Util_join("", dir, dir_sep, "lemon", exe_ext, NULL);
- char *lemon_c = chaz_Util_join(dir_sep, dir, "lemon.c", NULL);
-
- chaz_CFlags_enable_optimization(cflags);
- chaz_MakeFile_add_var(makefile, "LEMON_EXE", lemon_exe);
- rule = chaz_MakeFile_add_compiled_exe(makefile, "$(LEMON_EXE)", lemon_c,
- cflags);
-
- chaz_CFlags_destroy(cflags);
- free(lemon_c);
- free(lemon_exe);
- return rule;
+ chaz_MakeBinary *exe = chaz_MakeFile_add_exe(makefile, dir, "lemon");
+ chaz_MakeBinary_add_src_file(exe, dir, "lemon.c");
+ return exe;
}
chaz_MakeRule*
@@ -482,49 +609,6 @@
return rule;
}
-chaz_MakeRule*
-chaz_MakeFile_override_cflags(chaz_MakeFile *makefile, const char *obj,
- chaz_CFlags *cflags) {
- const char *obj_ext = chaz_CC_obj_ext();
- const char *cflags_string = chaz_CFlags_get_string(cflags);
- size_t obj_ext_len = strlen(obj_ext);
- size_t obj_len = strlen(obj);
- size_t base_len;
- char *src;
- char *command;
- chaz_MakeRule *rule;
-
- if (obj_len <= obj_ext_len) {
- chaz_Util_die("Invalid object file: %s", obj);
- }
-
- base_len = obj_len - obj_ext_len;
-
- if (strcmp(obj + base_len, obj_ext) != 0) {
- chaz_Util_die("Invalid object file: %s", obj);
- }
-
- src = malloc(base_len + sizeof(".c"));
- memcpy(src, obj, base_len);
- memcpy(src + base_len, ".c", sizeof(".c"));
-
- rule = chaz_MakeFile_add_rule(makefile, obj, src);
- if (chaz_CC_msvc_version_num()) {
- command = chaz_Util_join(" ", "$(CC) /nologo", cflags_string, "/c",
- src, "/Fo$@", NULL);
- }
- else {
- command = chaz_Util_join(" ", "$(CC)", cflags_string, "-c", src,
- "-o $@", NULL);
- }
- chaz_MakeRule_add_command(rule, command);
-
- free(command);
- free(src);
-
- return rule;
-}
-
void
chaz_MakeFile_write(chaz_MakeFile *makefile) {
FILE *out;
@@ -545,6 +629,10 @@
S_write_rule(makefile->rules[i], out);
}
+ for (i = 0; makefile->binaries[i]; i++) {
+ chaz_MakeFile_write_binary_rules(makefile, makefile->binaries[i], out);
+ }
+
S_write_rule(makefile->clean, out);
S_write_rule(makefile->distclean, out);
@@ -561,6 +649,122 @@
fclose(out);
}
+static void
+chaz_MakeFile_write_binary_rules(chaz_MakeFile *self, chaz_MakeBinary *binary,
+ FILE *out) {
+ const char *cflags;
+
+ if (chaz_CC_msvc_version_num()) {
+ chaz_CFlags_append(binary->link_flags, "/nologo");
+ }
+
+ switch (binary->type) {
+ case CHAZ_MAKEBINARY_EXE:
+ chaz_MakeFile_finish_exe(self, binary);
+ break;
+ case CHAZ_MAKEBINARY_STATIC_LIB:
+ chaz_MakeFile_finish_static_lib(self, binary);
+ break;
+ case CHAZ_MAKEBINARY_SHARED_LIB:
+ chaz_MakeFile_finish_shared_lib(self, binary);
+ break;
+ default:
+ chaz_Util_die("Invalid binary type: %d", binary->type);
+ return;
+ }
+
+ chaz_MakeRule_add_rm_command(self->clean, binary->rule->targets);
+ chaz_MakeRule_add_rm_command(self->clean, binary->dollar_var);
+
+ S_write_rule(binary->rule, out);
+
+ cflags = chaz_CFlags_get_string(binary->compile_flags);
+
+ /* Write rules to compile with custom flags. */
+ if (cflags[0] != '\0') {
+ if (chaz_Make.shell_type == CHAZ_OS_CMD_EXE) {
+ /* Write a rule for each object file. This is needed for nmake
+ * which doesn't support pattern rules but also for mingw32-make
+ * which has problems with pattern rules and backslash directory
+ * separators.
+ */
+ chaz_MakeFile_write_object_rules(binary->sources, cflags, out);
+ }
+ else {
+ /* Write a pattern rule for each directory. */
+ chaz_MakeFile_write_pattern_rules(binary->dirs, cflags, out);
+ /* Write a rule for each object added with add_src_file. */
+ chaz_MakeFile_write_object_rules(binary->single_sources, cflags,
+ out);
+ }
+ }
+}
+
+static void
+chaz_MakeFile_write_object_rules(char **sources, const char *cflags,
+ FILE *out) {
+ chaz_CFlags *output_cflags = chaz_CC_new_cflags();
+ const char *output_cflags_string;
+ size_t i;
+
+ chaz_CFlags_set_output_obj(output_cflags, "$@");
+ output_cflags_string = chaz_CFlags_get_string(output_cflags);
+
+ for (i = 0; sources[i]; i++) {
+ const char *source = sources[i];
+ char *obj_path = chaz_MakeBinary_obj_path(source);
+ chaz_MakeRule *rule;
+ char *command;
+
+ if (obj_path == NULL) { continue; }
+
+ rule = S_new_rule(obj_path, source);
+ command = chaz_Util_join(" ", "$(CC) $(CFLAGS)", cflags, source,
+ output_cflags_string, NULL);
+ chaz_MakeRule_add_command(rule, command);
+ S_write_rule(rule, out);
+
+ free(command);
+ S_destroy_rule(rule);
+ free(obj_path);
+ }
+
+ chaz_CFlags_destroy(output_cflags);
+}
+
+static void
+chaz_MakeFile_write_pattern_rules(char **dirs, const char *cflags, FILE *out) {
+ const char *obj_ext = chaz_CC_obj_ext();
+ const char *dir_sep = chaz_OS_dir_sep();
+ chaz_CFlags *output_cflags = chaz_CC_new_cflags();
+ const char *output_cflags_string;
+ char *command;
+ size_t i;
+
+ chaz_CFlags_set_output_obj(output_cflags, "$@");
+ output_cflags_string = chaz_CFlags_get_string(output_cflags);
+ command = chaz_Util_join(" ", "$(CC) $(CFLAGS)", cflags, "$<",
+ output_cflags_string, NULL);
+
+ for (i = 0; dirs[i]; i++) {
+ const char *dir = dirs[i];
+ char *target = chaz_Util_join("", dir, dir_sep, "%", obj_ext,
+ NULL);
+ char *prereq = chaz_Util_join("", dir, dir_sep, "%.c", NULL);
+ chaz_MakeRule *rule = S_new_rule(target, prereq);
+
+ chaz_MakeRule_add_command(rule, command);
+ S_write_rule(rule, out);
+
+ S_destroy_rule(rule);
+ free(prereq);
+ free(target);
+ }
+
+ free(command);
+ chaz_CFlags_destroy(output_cflags);
+}
+
void
chaz_MakeVar_append(chaz_MakeVar *var, const char *element) {
char *value;
@@ -791,6 +995,170 @@
}
}
+static void
+chaz_MakeBinary_destroy(chaz_MakeBinary *self) {
+ size_t i;
+
+ free(self->target_dir);
+ free(self->basename);
+ free(self->version);
+ free(self->major_version);
+ free(self->dollar_var);
+ S_destroy_rule(self->rule);
+
+ for (i = 0; i < self->num_sources; i++) {
+ free(self->sources[i]);
+ }
+ free(self->sources);
+ for (i = 0; i < self->num_single_sources; i++) {
+ free(self->single_sources[i]);
+ }
+ free(self->single_sources);
+ for (i = 0; i < self->num_dirs; i++) {
+ free(self->dirs[i]);
+ }
+ free(self->dirs);
+
+ chaz_CFlags_destroy(self->compile_flags);
+ chaz_CFlags_destroy(self->link_flags);
+
+ free(self);
+}
+
+void
+chaz_MakeBinary_add_src_file(chaz_MakeBinary *self, const char *dir,
+ const char *filename) {
+ size_t num_sources = self->num_single_sources;
+ size_t alloc_size = (num_sources + 2) * sizeof(char*);
+ char **sources = (char**)realloc(self->single_sources, alloc_size);
+ char *path;
+
+ if (dir == NULL || strcmp(dir, ".") == 0) {
+ path = chaz_Util_strdup(filename);
+ }
+ else {
+ const char *dir_sep = chaz_OS_dir_sep();
+ path = chaz_Util_join(dir_sep, dir, filename, NULL);
+ }
+
+ /* Add to single_sources. */
+ sources[num_sources] = path;
+ sources[num_sources+1] = NULL;
+ self->single_sources = sources;
+ self->num_single_sources = num_sources + 1;
+
+ chaz_MakeBinary_do_add_src_file(self, path);
+}
+
+void
+chaz_MakeBinary_add_src_dir(chaz_MakeBinary *self, const char *path) {
+ size_t num_dirs = self->num_dirs;
+ char **dirs = (char**)realloc(self->dirs, (num_dirs + 2) * sizeof(char*));
+
+ dirs[num_dirs] = chaz_Util_strdup(path);
+ dirs[num_dirs+1] = NULL;
+ self->dirs = dirs;
+ self->num_dirs = num_dirs + 1;
+
+ chaz_Make_list_files(path, "c", chaz_MakeBinary_list_files_callback,
+ self);
+}
+
+static void
+chaz_MakeBinary_list_files_callback(const char *dir, char *file,
+ void *context) {
+ const char *dir_sep = chaz_OS_dir_sep();
+ char *path = chaz_Util_join(dir_sep, dir, file, NULL);
+
+ chaz_MakeBinary_do_add_src_file((chaz_MakeBinary*)context, path);
+ free(path);
+}
+
+static void
+chaz_MakeBinary_do_add_src_file(chaz_MakeBinary *self, const char *path) {
+ size_t num_sources = self->num_sources;
+ size_t alloc_size = (num_sources + 2) * sizeof(char*);
+ char **sources = (char**)realloc(self->sources, alloc_size);
+ char *obj_path;
+
+ sources[num_sources] = chaz_Util_strdup(path);
+ sources[num_sources+1] = NULL;
+ self->sources = sources;
+ self->num_sources = num_sources + 1;
+
+ obj_path = chaz_MakeBinary_obj_path(path);
+ if (obj_path == NULL) {
+ chaz_Util_warn("Invalid source filename: %s", path);
+ }
+ else {
+ chaz_MakeVar_append(self->obj_var, obj_path);
+ free(obj_path);
+ }
+}
+
+static char*
+chaz_MakeBinary_obj_path(const char *src_path) {
+ const char *dir_sep = chaz_OS_dir_sep();
+ const char *obj_ext = chaz_CC_obj_ext();
+ size_t obj_ext_len = strlen(obj_ext);
+ size_t i = strlen(src_path);
+ char *retval;
+
+ while (i > 0) {
+ i -= 1;
+ if (src_path[i] == dir_sep[0]) { return NULL; }
+ if (src_path[i] == '.') { break; }
+ }
+
+ if (src_path[i] != '.') { return NULL; }
+
+ retval = (char*)malloc(i + obj_ext_len + 1);
+ memcpy(retval, src_path, i);
+ memcpy(retval + i, obj_ext, obj_ext_len + 1);
+
+ return retval;
+}
+
+void
+chaz_MakeBinary_add_prereq(chaz_MakeBinary *self, const char *prereq) {
+ chaz_MakeRule_add_prereq(self->rule, prereq);
+}
+
+char*
+chaz_MakeBinary_obj_string(chaz_MakeBinary *self) {
+ char *retval = chaz_Util_strdup("");
+ size_t i;
+
+ for (i = 0; i < self->num_sources; i++) {
+ const char *sep = retval[0] == '\0' ? "" : " ";
+ char *obj_path = chaz_MakeBinary_obj_path(self->sources[i]);
+ char *tmp;
+
+ if (obj_path == NULL) { continue; }
+
+ tmp = chaz_Util_join("", retval, sep, obj_path, NULL);
+ free(retval);
+ retval = tmp;
+ }
+
+ return retval;
+}
+
+const char*
+chaz_MakeBinary_get_target(chaz_MakeBinary *self) {
+ return self->rule->targets;
+}
+
+chaz_CFlags*
+chaz_MakeBinary_get_compile_flags(chaz_MakeBinary *self) {
+ return self->compile_flags;
+}
+
+chaz_CFlags*
+chaz_MakeBinary_get_link_flags(chaz_MakeBinary *self) {
+ return self->link_flags;
+}
+
void
chaz_Make_list_files(const char *dir, const char *ext,
chaz_Make_list_files_callback_t callback, void *context) {
diff --git a/src/Charmonizer/Core/Make.h b/src/Charmonizer/Core/Make.h
index 25e99ea..f2ab064 100644
--- a/src/Charmonizer/Core/Make.h
+++ b/src/Charmonizer/Core/Make.h
@@ -25,11 +25,11 @@
#endif
#include "Charmonizer/Core/CFlags.h"
-#include "Charmonizer/Core/Library.h"
typedef struct chaz_MakeFile chaz_MakeFile;
typedef struct chaz_MakeVar chaz_MakeVar;
typedef struct chaz_MakeRule chaz_MakeRule;
+typedef struct chaz_MakeBinary chaz_MakeBinary;
typedef void (*chaz_Make_list_files_callback_t)(const char *dir, char *file,
void *context);
@@ -117,59 +117,44 @@
chaz_MakeRule*
chaz_MakeFile_distclean_rule(chaz_MakeFile *makefile);
-/** Add a rule to link an executable. The executable will also be added to the
- * list of files to clean.
+/** Add an executable. Returns a chaz_MakeBinary object.
*
- * @param makefile The makefile.
- * @param exe The name of the executable.
- * @param sources The list of source files.
- * @param link_flags Additional link flags.
+ * @param dir The target directory or NULL for the current directory.
+ * @param basename The name of the executable without extension.
*/
-chaz_MakeRule*
-chaz_MakeFile_add_exe(chaz_MakeFile *makefile, const char *exe,
- const char *sources, chaz_CFlags *link_flags);
+chaz_MakeBinary*
+chaz_MakeFile_add_exe(chaz_MakeFile *self, const char *dir,
+ const char *basename);
-/** Add a rule to compile and link an executable. The executable will also be
- * added to the list of files to clean.
+/** Add a shared library. The library will be built in the current directory.
+ * Returns a chaz_MakeBinary object.
*
- * @param makefile The makefile.
- * @param exe The name of the executable.
- * @param sources The list of source files.
- * @param cflags Additional compiler flags.
+ * @param dir The target directory or NULL for the current directory.
+ * @param basename The name of the library without prefix and extension.
+ * @param version The version of the library.
+ * @param major_version The major version of the library.
*/
-chaz_MakeRule*
-chaz_MakeFile_add_compiled_exe(chaz_MakeFile *makefile, const char *exe,
- const char *sources, chaz_CFlags *cflags);
+chaz_MakeBinary*
+chaz_MakeFile_add_shared_lib(chaz_MakeFile *self, const char *dir,
+ const char *basename, const char *version,
+ const char *major_version);
-/** Add a rule to link a shared library. The shared library will also be added
- * to the list of files to clean.
+/** Add a static library. The library will be built in the current directory.
+ * Returns a chaz_MakeBinary object.
*
- * @param makefile The makefile.
- * @param lib The shared library.
- * @param sources The list of source files.
- * @param link_flags Additional link flags.
+ * @param dir The target directory or NULL for the current directory.
+ * @param basename The name of the library without prefix and extension.
*/
-chaz_MakeRule*
-chaz_MakeFile_add_shared_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
- const char *sources, chaz_CFlags *link_flags);
-
-/** Add a rule to create a static library. The static library will also be added
- * to the list of files to clean.
- *
- * @param makefile The makefile.
- * @param lib The static library.
- * @param objects The list of object files to be archived.
- */
-chaz_MakeRule*
-chaz_MakeFile_add_static_lib(chaz_MakeFile *makefile, chaz_Lib *lib,
- const char *objects);
+chaz_MakeBinary*
+chaz_MakeFile_add_static_lib(chaz_MakeFile *self, const char *dir,
+ const char *basename);
/** Add a rule to build the lemon parser generator.
*
* @param makefile The makefile.
* @param dir The lemon directory.
*/
-chaz_MakeRule*
+chaz_MakeBinary*
chaz_MakeFile_add_lemon_exe(chaz_MakeFile *makefile, const char *dir);
/** Add a rule for a lemon grammar.
@@ -181,16 +166,6 @@
chaz_MakeFile_add_lemon_grammar(chaz_MakeFile *makefile,
const char *base_name);
-/** Override compiler flags for a single object file.
- *
- * @param makefile The makefile.
- * @param obj The object file.
- * @param cflags Compiler flags.
- */
-chaz_MakeRule*
-chaz_MakeFile_override_cflags(chaz_MakeFile *makefile, const char *obj,
- chaz_CFlags *cflags);
-
/** Write the makefile to a file named 'Makefile' in the current directory.
*
* @param makefile The makefile.
@@ -267,6 +242,49 @@
chaz_MakeRule_add_make_command(chaz_MakeRule *rule, const char *dir,
const char *target);
+/** Add a source file for the binary.
+ *
+ * @param dir The source directory or NULL for the current directory.
+ * @param filename The filename.
+ */
+void
+chaz_MakeBinary_add_src_file(chaz_MakeBinary *self, const char *dir,
+ const char *filename);
+
+/** Add all .c files in a directory as sources for the binary.
+ *
+ * @param path The path to the directory.
+ */
+void
+chaz_MakeBinary_add_src_dir(chaz_MakeBinary *self, const char *path);
+
+/** Add a prerequisite to the make rule of the binary.
+ *
+ * @param prereq The prerequisite.
+ */
+void
+chaz_MakeBinary_add_prereq(chaz_MakeBinary *self, const char *prereq);
+
+/** Return a list of all objects separated by space.
+ */
+char*
+chaz_MakeBinary_obj_string(chaz_MakeBinary *self);
+
+/** Accessor for target.
+ */
+const char*
+chaz_MakeBinary_get_target(chaz_MakeBinary *self);
+
+/** Accessor for compile flags.
+ */
+chaz_CFlags*
+chaz_MakeBinary_get_compile_flags(chaz_MakeBinary *self);
+
+/** Accessor for link flags.
+ */
+chaz_CFlags*
+chaz_MakeBinary_get_link_flags(chaz_MakeBinary *self);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/Charmonizer/Probe/Floats.c b/src/Charmonizer/Probe/Floats.c
index 609bee8..e2f8d41 100644
--- a/src/Charmonizer/Probe/Floats.c
+++ b/src/Charmonizer/Probe/Floats.c
@@ -90,7 +90,7 @@
return NULL;
}
- chaz_CFlags_add_external_library(temp_cflags, "m");
+ chaz_CFlags_add_external_lib(temp_cflags, "m");
output = chaz_CC_capture_output(sqrt_code, &output_len);
chaz_CFlags_clear(temp_cflags);