Skip to content

Commit

Permalink
feat: linux self hosting now (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
zaucy authored Aug 11, 2024
1 parent 1a5688c commit f837526
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 28 deletions.
2 changes: 1 addition & 1 deletion share/cpp2b.build.cppm.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module;
#if defined(_WIN32)
# define CPP2B_BUILD_API extern "C" __declspec(dllexport)
#else
# define CPP2B_BUILD_API __attribute__((visibility("default")))
# define CPP2B_BUILD_API extern "C" __attribute__((visibility("default")))
#endif

export module cpp2b.build;
Expand Down
28 changes: 28 additions & 0 deletions share/cpp2b.cppm.tpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
module;

#ifdef _MSC_VER
# include <Windows.h>
#else
# include <stdlib.h>
#endif

export module cpp2b;

import std;
import std.compat;

export namespace cpp2b {
Expand Down Expand Up @@ -48,3 +57,22 @@ constexpr auto install_dir() -> const std::string_view {
}

} // namespace cpp2b

export namespace cpp2b::env {
inline auto set_var(const std::string& name, const std::string& value) -> void {
#if defined(_MSC_VER)
SetEnvironmentVariableA(name.c_str(), value.c_str());
#else
setenv(name.c_str(), value.c_str(), 1);
#endif
}

inline auto get_var(const std::string& name) -> std::optional<std::string> {
auto val = std::getenv(name.c_str());
if(val != nullptr) {
return std::string{val};
}

return {};
}
}
132 changes: 105 additions & 27 deletions src/main.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,15 @@ run_with_msvc_env_vars: (args) -> int = {
return std::system(cmd_str.c_str());
}

run_with_args: (args) -> int = {
cmd_str: std::string = "";
for args do (arg) {
cmd_str += " (arg)$";
}

return std::system(cmd_str.c_str());
}

main: (args) -> int = {
using std::views::drop;

Expand All @@ -324,6 +333,14 @@ main: (args) -> int = {
} else {
log_info("using vs tools {}", getenv_sv("VCToolsVersion").expect("msvc env internal error"));
}
} else {
libcxx_lib_dir := get_libcxx_build_root() / "lib";
ld_library_path := cpp2b::env::get_var("LD_LIBRARY_PATH");
if !ld_library_path || !ld_library_path*.contains(libcxx_lib_dir.string()) {
log_info("setting LD_LIBRARY_PATH to '{}'", libcxx_lib_dir.string());
cpp2b::env::set_var("LD_LIBRARY_PATH", libcxx_lib_dir.string());
return run_with_args(argz);
}
}

ensure_dir(".cache/cpp2/mod");
Expand Down Expand Up @@ -497,7 +514,47 @@ build_binary_result: @struct type = {
log_path: fs::path = ();
duration: std::chrono::milliseconds = ();
}

cl_build_binary_cmd: (info: cpp2b_source_binary_info, bin_outpath: fs::path) -> std::string = {
cppfront_include_dir := fs::absolute(".cache/cpp2/repos/hsutter/cppfront/include");
transpiled_src := fs::absolute(".cache/cpp2/source") / fs::path(info.src).replace_extension(".cpp");
d := fs::absolute(modules_dir());
cmd_str: std::string = "cl /nologo /std:c++latest /W4 /MDd /EHsc /DEBUG:full /Zi /FC";
for info.imports do (imp: std::string) {
imp_bmi := d / ("(imp)$.ifc");
imp_obj := d / ("(imp)$.obj");
cmd_str += " /reference \"(imp_bmi.string())$\" \"(imp_obj.string())$\"";
}
cmd_str += " \"(transpiled_src.string())$\"";
cmd_str += " -I\"(cppfront_include_dir.string())$\"";
cmd_str += " /Fe\"(bin_outpath.string())$\"";
return cmd_str;
}

unix_build_binary_cmd: (compiler_cmd: std::string, info: cpp2b_source_binary_info, bin_outpath: fs::path) -> std::string = {
libcxx_inc_dir := get_libcxx_build_root() / "include" / "c++" / "v1";
libcxx_lib_dir := get_libcxx_build_root() / "lib";
cppfront_include_dir := fs::absolute(".cache/cpp2/repos/hsutter/cppfront/include");
transpiled_src := fs::absolute(".cache/cpp2/source") / fs::path(info.src).replace_extension(".cpp");
d := fs::absolute(modules_dir());
cmd_str: std::string = std::format("{} -stdlib=libc++ -fPIC", compiler_cmd);
for info.imports do (imp: std::string) {
cmd_str += " \"" + (d / ("(imp)$.pcm")).string() + "\"";
}
cmd_str += " \"(transpiled_src.string())$\"";
cmd_str += " -std=c++23 -fexperimental-library";
cmd_str += std::format(" -fprebuilt-module-path={}", d.string());
cmd_str += std::format(" -L{}", libcxx_lib_dir.string());
cmd_str += std::format(" -isystem {}", libcxx_inc_dir.string());
cmd_str += " -lc++abi -lc++ -lm -static -fuse-ld=lld";
cmd_str += " -I\"(cppfront_include_dir.string())$\"";
cmd_str += " -o \"(bin_outpath.string())$\"";
return cmd_str;
}


build_binary: (info: cpp2b_source_binary_info) -> build_binary_result = {
compiler :== cpp2b::compiler();
bin_basename: fs::path;
if info.preferred_name {
bin_basename = fs::path(info.preferred_name*);
Expand All @@ -512,28 +569,19 @@ build_binary: (info: cpp2b_source_binary_info) -> build_binary_result = {
bin_basename.replace_extension(executable_extension());
}

cppfront_include_dir := fs::absolute(".cache/cpp2/repos/hsutter/cppfront/include");
bin_outpath := fs::absolute(".cache/cpp2/bin") / bin_basename;
transpiled_src := fs::absolute(".cache/cpp2/source") / fs::path(info.src).replace_extension(".cpp");
log_path := fs::absolute(".cache/cpp2/log/compile") / fs::path(info.src).replace_extension(".log");
ensure_dir(log_path.parent_path());
ensure_dir(bin_outpath.parent_path());

if cpp2b::compiler() != cpp2b::compiler_type::msvc {
log_error("TODO: build_binary non-msvc support");
std::abort();
}

d := fs::absolute(modules_dir());
cmd_str: std::string = "cl /nologo /std:c++latest /W4 /MDd /EHsc /DEBUG:full /Zi /FC";
for info.imports do (imp: std::string) {
imp_bmi := d / ("(imp)$.ifc");
imp_obj := d / ("(imp)$.obj");
cmd_str += " /reference \"(imp_bmi.string())$\" \"(imp_obj.string())$\"";
}
cmd_str += " \"(transpiled_src .string())$\"";
cmd_str += " -I\"(cppfront_include_dir.string())$\"";
cmd_str += " /Fe\"(bin_outpath.string())$\"";

cmd_str: std::string = "";
if compiler == cpp2b::compiler_type::msvc { cmd_str = cl_build_binary_cmd(info, bin_outpath); }
else if compiler == cpp2b::compiler_type::clang { cmd_str = unix_build_binary_cmd("clang", info, bin_outpath); }
else if compiler == cpp2b::compiler_type::gcc { cmd_str = unix_build_binary_cmd("gcc", info, bin_outpath); }
else { log_error("Unsupported compiler"); std::abort(); }

cmd_str += " (cmd_log_output(fs::absolute(log_path)))$";

result: build_binary_result = ();
Expand Down Expand Up @@ -568,19 +616,9 @@ cpp2b_detail_build: (copy _impl: *cpp2b_detail_build_impl) -> void = {
// empty. this is just so we can decltype the signature
}

build_build_script: (info: cpp2b_source_build_info) -> build_binary_result = {
cl_build_build_script_cmd: (info: cpp2b_source_build_info, bin_outpath: fs::path) -> std::string = {
cppfront_include_dir := fs::absolute(".cache/cpp2/repos/hsutter/cppfront/include");
bin_outpath := fs::absolute(".cache/cpp2/bin") / fs::path(info.src).replace_extension(shared_library_extension());
transpiled_src := fs::absolute(".cache/cpp2/source") / fs::path(info.src).replace_extension(".cpp");
log_path := fs::absolute(".cache/cpp2/log/compile") / fs::path(info.src).replace_extension(".log");
ensure_dir(log_path.parent_path());
ensure_dir(bin_outpath.parent_path());

if cpp2b::compiler() != cpp2b::compiler_type::msvc {
log_error("TODO: build_build_script non-msvc support");
std::abort();
}

d := fs::absolute(modules_dir());
cmd_str: std::string = "cl /nologo /std:c++latest /W4 /MDd /EHsc /LDd /DLL";
for info.imports do (imp: std::string) {
Expand All @@ -592,6 +630,46 @@ build_build_script: (info: cpp2b_source_build_info) -> build_binary_result = {
cmd_str += " -I\"(cppfront_include_dir.string())$\"";
cmd_str += " /Fe\"(fs::relative(bin_outpath).string())$\"";
cmd_str += " /link";
return cmd_str;
}


unix_build_build_script_cmd: (compiler_cmd: std::string, info: cpp2b_source_build_info, bin_outpath: fs::path) -> std::string = {
libcxx_inc_dir := get_libcxx_build_root() / "include" / "c++" / "v1";
libcxx_lib_dir := get_libcxx_build_root() / "lib";
cppfront_include_dir := fs::absolute(".cache/cpp2/repos/hsutter/cppfront/include");
transpiled_src := fs::absolute(".cache/cpp2/source") / fs::path(info.src).replace_extension(".cpp");
d := fs::absolute(modules_dir());
cmd_str: std::string = std::format("{} -stdlib=libc++ -shared", compiler_cmd);
for info.imports do (imp: std::string) {
cmd_str += " \"" + (d / ("(imp)$.pcm")).string() + "\"";
}
cmd_str += " \"(transpiled_src.string())$\"";
cmd_str += " -std=c++23 -fexperimental-library -fPIC";
cmd_str += std::format(" -fprebuilt-module-path={}", d.string());
cmd_str += std::format(" -L{}", libcxx_lib_dir.string());
cmd_str += std::format(" -isystem {}", libcxx_inc_dir.string());
cmd_str += " -lc++abi -lc++ -lm -fuse-ld=lld";
cmd_str += " -I\"(cppfront_include_dir.string())$\"";
cmd_str += " -o \"(bin_outpath.string())$\"";
return cmd_str;
}


build_build_script: (info: cpp2b_source_build_info) -> build_binary_result = {
compiler :== cpp2b::compiler();
bin_outpath := fs::absolute(".cache/cpp2/bin") / fs::path(info.src).replace_extension(shared_library_extension());
log_path := fs::absolute(".cache/cpp2/log/compile") / fs::path(info.src).replace_extension(".log");
ensure_dir(log_path.parent_path());
ensure_dir(bin_outpath.parent_path());

d := fs::absolute(modules_dir());
cmd_str: std::string = "";
if compiler == cpp2b::compiler_type::msvc { cmd_str = cl_build_build_script_cmd(info, bin_outpath); }
else if compiler == cpp2b::compiler_type::clang { cmd_str = unix_build_build_script_cmd("clang", info, bin_outpath); }
else if compiler == cpp2b::compiler_type::gcc { cmd_str = unix_build_build_script_cmd("gcc", info, bin_outpath); }
else { log_error("Unsupported compiler"); std::abort(); }

cmd_str += " (cmd_log_output(fs::relative(log_path)))$";

result: build_binary_result = ();
Expand Down

0 comments on commit f837526

Please sign in to comment.