Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: linux self hosting now #3

Merged
merged 3 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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