step towards c++
This commit is contained in:
@@ -11,6 +11,12 @@ static class Program
|
||||
|
||||
public static int Main(String[] args)
|
||||
{
|
||||
if (args.Count == 3 && args[0] == "---__defsyms__")
|
||||
{
|
||||
GenerateAliases(args);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mixin PrintUsage()
|
||||
{
|
||||
Console.WriteLine("""
|
||||
@@ -19,8 +25,9 @@ static class Program
|
||||
Usage: $(Var CxxBuilderExe) [<options>] <patterns...> -- src=<> target=<> config=<> builddir=<> output=<> [cflags=<>]
|
||||
Example: $(Var CxxBuilderExe) **.c vk_*.cpp -- "src=$(ProjectDir)/MyLib/src" target=$(TargetTriple) config=$(Configuration) "builddir=$(BuildDir)" output=MyLib cflags=-Isome/dir
|
||||
|
||||
--template - TODO
|
||||
--cmake - builds $src/CMakeLists.txt to build, patterns and output are ignored
|
||||
! --template - TODO
|
||||
! --cpp-aliases - creates aliases from the mangled c++ symbols to the symbols queried by Cpp2Beef-generated c++ bindigs
|
||||
|
||||
$src - The source dir, all patterns are rooted here
|
||||
$target - the llvm target triple passed to clang
|
||||
@@ -36,27 +43,36 @@ static class Program
|
||||
{
|
||||
if (!condition)
|
||||
{
|
||||
Console.WriteLine(str);
|
||||
Console.Error.WriteLine(str);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
enum { Default, CMake, Template } mode = .Default;
|
||||
enum { None, CppAliases } actions = .None;
|
||||
StringView src = null, target = null, config = null, builddir = null, output = null, cflags = null;
|
||||
var iter = args.GetEnumerator();
|
||||
skipPatterns: do
|
||||
{
|
||||
for (let arg in iter)
|
||||
{
|
||||
if (arg == "--") break skipPatterns;
|
||||
if (arg == "--cmake")
|
||||
if (!arg.StartsWith("--")) continue;
|
||||
switch (arg)
|
||||
{
|
||||
case "--": break skipPatterns;
|
||||
case "--cmake":
|
||||
Assert!(mode == .Default, "Conflicting options");
|
||||
mode = .CMake;
|
||||
/*case "--cpp-aliases":
|
||||
actions |= .CppAliases;*/
|
||||
default:
|
||||
Console.Error.WriteLine($"Invalid option {_}");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
PrintUsage!();
|
||||
}
|
||||
Assert!(!(mode == .CMake && actions.HasFlag(.CppAliases)), "Comflicting options --cmake and --cpp-aliases");
|
||||
for (let arg in iter)
|
||||
{
|
||||
var parts = arg.Split('=', 2);
|
||||
@@ -84,7 +100,7 @@ static class Program
|
||||
Assert!(!target.IsNull, "Missing var 'target'");
|
||||
Assert!(!config.IsNull, "Missing var 'config'");
|
||||
Assert!(!builddir.IsNull, "Missing var 'builddir'");
|
||||
Assert!(!output.IsNull || mode == .CMake, "Missing var 'output'");
|
||||
Assert!(!output.IsNull || (mode == .CMake && !actions.HasFlag(.CppAliases)), "Missing var 'output'");
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
@@ -104,14 +120,14 @@ static class Program
|
||||
WriteVarPath("builddir", builddir);
|
||||
buffer.AppendF($"""
|
||||
target = {target}
|
||||
cflags = {(config == "Release") ? "-O2" : "-O2 -g"} {cflags}
|
||||
cflags = {(config == "Release") ? "-O3" : "-O2 -g"} {cflags}
|
||||
""");
|
||||
writer.Write(buffer);
|
||||
}
|
||||
writer.Write("""
|
||||
\n
|
||||
cc = clang
|
||||
ar = ar
|
||||
ar = llvm-ar
|
||||
|
||||
rule cc
|
||||
command = $cc $cflags -target $target -MD -MF $out.d -c -o $out $in
|
||||
@@ -126,7 +142,8 @@ static class Program
|
||||
|
||||
""");
|
||||
String ar = scope .(1024);
|
||||
ar.AppendF($"\nbuild $builddir/{output}.{target.Contains("windows") ? "lib" : "a"}: ar");
|
||||
StringView libExtension = target.Contains("windows") ? "lib" : "a";
|
||||
ar.AppendF($"\nbuild $builddir/{output}.{libExtension}: ar");
|
||||
|
||||
int pcount = 0;
|
||||
for (let arg in args)
|
||||
@@ -148,11 +165,45 @@ static class Program
|
||||
let abssrc = Path.GetAbsolutePath(src, Directory.GetCurrentDirectory(..scope .(128)), ..scope .(128));
|
||||
if (FileMatcher.HandleMatches(patterns, abssrc, scope => HandleMatch) case .Err(let err))
|
||||
{
|
||||
Console.WriteLine($"Syntax Error in Pattern: {err}");
|
||||
Console.Error.WriteLine($"Syntax Error in Pattern: {err}");
|
||||
return 1;
|
||||
}
|
||||
|
||||
writer.WriteLine(ar);
|
||||
|
||||
if (actions.HasFlag(.CppAliases))
|
||||
{
|
||||
const String exec = .Empty
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
+ "cmd /c ";
|
||||
#endif
|
||||
writer.Write($"""
|
||||
|
||||
nm = llvm-nm
|
||||
ld = {exec}ld
|
||||
|
||||
rule nm
|
||||
command = {exec}$nm --demangle $in > $out
|
||||
description = Exporting symbols from $in
|
||||
|
||||
rule generate_aliases
|
||||
command = "{Environment.GetExecutableFilePath(..scope .(64))}" ---__defsyms__ $in $out
|
||||
description = Generating aliases
|
||||
|
||||
rule ld_aliases
|
||||
command = $ld -r -o $out @$in "$builddir/{output}.{libExtension}"
|
||||
description = Creating aliases
|
||||
|
||||
rule ar_add
|
||||
command = $ar qs $builddir/{output}.{libExtension} $in
|
||||
|
||||
build $builddir/_symbols__.txt: nm $builddir/{output}.{libExtension}
|
||||
build $builddir/_aliases__.txt: generate_aliases $builddir/_symbols__.txt
|
||||
build $builddir/_aliases__.o: ld_aliases $builddir/_aliases__.txt
|
||||
build add_to_output: ar_add $builddir/_aliases__.o
|
||||
|
||||
""");
|
||||
}
|
||||
case .CMake:
|
||||
#if !DEBUG
|
||||
if (File.Exists(scope $"{builddir}/build.ninja"))
|
||||
@@ -167,9 +218,84 @@ static class Program
|
||||
case .Template: //TODO
|
||||
}
|
||||
|
||||
let ret = system(scope $"ninja -C {builddir}");
|
||||
if (ret != 0)
|
||||
Console.WriteLine($"Failed to build {output}");
|
||||
return ret;
|
||||
var ret = system(scope $"ninja -C {builddir}");
|
||||
mixin CheckRetCode(StringView fmt)
|
||||
{
|
||||
if (ret != 0)
|
||||
{
|
||||
Console.Error.WriteLine(fmt, output);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
CheckRetCode!("Failed to build {}");
|
||||
|
||||
/*if (actions.HasFlag(.CppAliases))
|
||||
{
|
||||
let aliasesDir = scope $"{builddir}/cpp2beef_aliases";
|
||||
Directory.CreateDirectory(aliasesDir);
|
||||
{
|
||||
StreamWriter writer = scope .()..Create(scope $"{aliasesDir}/aliases.c");
|
||||
ret = system(scope $"llvm-nm --export-symbols \"{builddir}/{output}.{target.Contains("windows") ? "lib" : "a"}\" > {aliasesDir}/mangled.txt");
|
||||
CheckRetCode!("Failed to fetch symbols from {}");
|
||||
ret = system(scope $"cat {aliasesDir}/mangled.txt | llvm-undname >{aliasesDir}/demangled.txt 2>{
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
("nul")
|
||||
#else
|
||||
("/dev/null")
|
||||
#endif
|
||||
}");
|
||||
CheckRetCode!("Failed to demangle symbols from {}");
|
||||
var mangled = scope StreamReader()..Open(scope $"{aliasesDir}/magled.txt").Lines;
|
||||
var demangled = scope StreamReader()..Open(scope $"{aliasesDir}/demangled.txt").Lines;
|
||||
for (let dline in demangled)
|
||||
{
|
||||
if (dline->IsEmpty) continue;
|
||||
let mline = mangled.GetNext().Value;
|
||||
if (mline == dline) continue;
|
||||
String identifier = scope .(dline);
|
||||
for (let i < identifier.Length)
|
||||
if (!identifier[i].IsLetterOrDigit)
|
||||
identifier[i] = '_';
|
||||
writer.Write($"extern void {identifier}() __attribute__((weak, alias(\"{mline.Value}\")));\n");
|
||||
}
|
||||
}
|
||||
File.WriteAllText(scope $"{aliasesDir}/build.ninja", scope $"""
|
||||
rule cc
|
||||
command = clang -x c -target {target} -c -o $out $in
|
||||
description = Compiling aliases for {output}
|
||||
|
||||
build aliases.o: cc aliases.c
|
||||
|
||||
""");
|
||||
ret = system(scope $"ninja -C {aliasesDir}");
|
||||
CheckRetCode!("Failed to build aliases for {}");
|
||||
}*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void GenerateAliases(String[] args)
|
||||
{
|
||||
StreamReader reader = scope .()..Open(args[1]);
|
||||
StreamWriter writer = scope .()..Create(args[2]);
|
||||
String str = scope .(256);
|
||||
for (var line in reader.Lines)
|
||||
{
|
||||
line->Trim();
|
||||
if (line->IsEmpty || line->EndsWith(':')) continue;
|
||||
var split = line->Split(' ', 3);
|
||||
if (split.GetNext().Value == "U") continue;
|
||||
int addr = int.Parse(split.Current, .Hex);
|
||||
let kind = split.GetNext().Value;
|
||||
if (kind != "T" || addr == 0) continue;
|
||||
let sym = split.GetNext().Value;
|
||||
if (!str.IsEmpty) str..Clear()..Append(' ');
|
||||
str.Append("--defsym=");
|
||||
for (let i < sym.Length)
|
||||
str.Append(sym[i].IsLetterOrDigit ? sym[i] : '_');
|
||||
str.Append('=');
|
||||
addr.ToString(str);
|
||||
writer.Write(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user