summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2026-02-23 21:03:11 +0100
committerBent Bisballe Nyeng <deva@aasimon.org>2026-02-25 17:09:10 +0100
commit5a3e0931e0e4ccd252c527b512ec1634d57489d8 (patch)
tree6df26db1090d6edfe4430fb6dd9871465b56e32a
parent2855b6e1172d5b544b150bf617b216691801f574 (diff)
WIP
-rwxr-xr-xbootstrap.sh2
-rw-r--r--ctor.cc10
-rw-r--r--src/bootstrap.cc2
-rw-r--r--src/ctor.h78
-rw-r--r--src/libctor.cc124
-rw-r--r--src/rebuild.cc1
-rw-r--r--test/ctor.cc27
7 files changed, 232 insertions, 12 deletions
diff --git a/bootstrap.sh b/bootstrap.sh
index 4dd57ae..9c573f7 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -7,6 +7,6 @@ set -e
echo "Bootstrapping..."
$CXX $LDFLAGS $CXXFLAGS -std=c++20 -Wall -O3 -Isrc -pthread src/bootstrap.cc ctor.cc -o ctor
./ctor
-$CXX $LDFLAGS $CXXFLAGS -std=c++20 -Wall -O3 -Isrc -pthread ctor.cc test/ctor.cc -L$BUILDDIR -lctor -o ctor
+$CXX $LDFLAGS $CXXFLAGS -std=c++20 -Wall -O3 -Isrc -pthread ctor.cc test/ctor.cc -L$BUILDDIR -lctor -larchive -o ctor
./ctor configure --ctor-includedir=src --ctor-libdir=$BUILDDIR --build-dir=$BUILDDIR
echo "Done. Now run ./ctor to (re)build."
diff --git a/ctor.cc b/ctor.cc
index e610801..f485309 100644
--- a/ctor.cc
+++ b/ctor.cc
@@ -10,6 +10,7 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings)
return
{
{
+ ctor::project{"libctor", {1,0,0, "rc1"}},
ctor::output_system::build,
ctor::target("libctor.a"),
ctor::sources{
@@ -66,6 +67,15 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings)
"-Isrc",
"-fexceptions",
},
+ ctor::ld_flags{
+ "-larchive",
+ },
+ ctor::extra_dist{
+ "LICENSE",
+ "README.md",
+ "src/bootstrap.cc",
+ "bootstrap.sh",
+ }
}
};
}
diff --git a/src/bootstrap.cc b/src/bootstrap.cc
index 836504e..1ab4f31 100644
--- a/src/bootstrap.cc
+++ b/src/bootstrap.cc
@@ -121,7 +121,7 @@ int main(int argc, char* argv[])
settings.builddir = c.get(ctor::cfg::builddir, settings.builddir);
settings.parallel_processes =
std::max(1u, std::thread::hardware_concurrency() * 2 - 1);
- settings.verbose = 0;
+ settings.verbose = 1;
auto all_tasks = getTasks(settings, {}, false);
for(auto task : all_tasks)
{
diff --git a/src/ctor.h b/src/ctor.h
index 9320c3d..665ab75 100644
--- a/src/ctor.h
+++ b/src/ctor.h
@@ -75,6 +75,11 @@ enum class source_type
generated,
};
+struct nodist
+{
+ bool value{true};
+};
+
struct source
{
template <class ... Args>
@@ -83,7 +88,8 @@ struct source
std::is_same_v<Args, ctor::toolchain> ||
std::is_same_v<Args, ctor::language> ||
std::is_same_v<Args, ctor::source_type> ||
- std::is_same_v<Args, ctor::output_file>
+ std::is_same_v<Args, ctor::output_file> ||
+ std::is_same_v<Args, ctor::nodist>
) && ...)
constexpr source(Args && ... arg)
{
@@ -109,6 +115,10 @@ struct source
{
source_type = arg;
}
+ else if constexpr(std::is_same_v<Args, ctor::nodist>)
+ {
+ nodist = arg.value;
+ }
}(), ...);
}
@@ -117,6 +127,7 @@ struct source
ctor::language language{ctor::language::automatic};
std::string output{};
ctor::source_type source_type{ctor::source_type::regular};
+ bool nodist{false};
};
using sources = std::vector<ctor::source>;
@@ -125,7 +136,8 @@ struct header
{
template <class ... Args>
requires ((
- std::is_convertible_v<Args, std::string_view>
+ std::is_convertible_v<Args, std::string_view> ||
+ std::is_same_v<Args, ctor::nodist>
) && ...)
constexpr header(Args && ... arg)
{
@@ -135,19 +147,47 @@ struct header
{
file = arg;
}
- else if constexpr(std::is_same_v<Args, ctor::install>)
+ else if constexpr(std::is_same_v<Args, ctor::nodist>)
{
- install = arg;
+ nodist = arg.value;
}
}(), ...);
}
std::string file;
- ctor::install install;
+ bool nodist{false};
};
using headers = std::vector<ctor::header>;
+struct extra_dist_file
+{
+ template <class ... Args>
+ requires ((
+ std::is_convertible_v<Args, std::string_view> ||
+ std::is_same_v<Args, ctor::nodist>
+ ) && ...)
+ constexpr extra_dist_file(Args && ... arg)
+ {
+ ([&]
+ {
+ if constexpr(std::is_convertible_v<Args, std::string_view>)
+ {
+ file = arg;
+ }
+ else if constexpr(std::is_same_v<Args, ctor::nodist>)
+ {
+ nodist = arg.value;
+ }
+ }(), ...);
+ }
+
+ std::string file;
+ bool nodist{false};
+};
+
+using extra_dist = std::vector<ctor::extra_dist_file>;
+
enum class cxx_opt
{
// gcc/clang
@@ -381,16 +421,32 @@ struct externals
std::vector<std::string> externals;
};
+struct version
+{
+ int major;
+ int minor;
+ int patch;
+ std::string tweak{};
+};
+
+struct project
+{
+ std::string name;
+ ctor::version version;
+};
+
struct build_configuration
{
template <class ... Args>
requires ((
+ std::is_same_v<Args, ctor::project> ||
std::is_same_v<Args, ctor::name> ||
std::is_same_v<Args, ctor::target_type> ||
std::is_same_v<Args, ctor::output_system> ||
std::is_same_v<Args, ctor::target> ||
std::is_same_v<Args, ctor::sources> ||
std::is_same_v<Args, ctor::headers> ||
+ std::is_same_v<Args, ctor::extra_dist> ||
std::is_same_v<Args, ctor::depends> ||
std::is_same_v<Args, ctor::externals> ||
std::is_convertible_v<Args, ctor::GeneratorOneToOne> ||
@@ -405,7 +461,11 @@ struct build_configuration
{
([&]
{
- if constexpr(std::is_same_v<Args, ctor::name>)
+ if constexpr(std::is_same_v<Args, ctor::project>)
+ {
+ project = arg;
+ }
+ else if constexpr(std::is_same_v<Args, ctor::name>)
{
name = arg.name;
}
@@ -429,6 +489,10 @@ struct build_configuration
{
headers = arg;
}
+ else if constexpr(std::is_same_v<Args, ctor::extra_dist>)
+ {
+ extra_dist = arg;
+ }
else if constexpr(std::is_same_v<Args, ctor::depends>)
{
depends = arg.depends;
@@ -468,12 +532,14 @@ struct build_configuration
}(), ...);
}
+ ctor::project project{};
std::string name; // Name - used for referring in other configurations.
ctor::target_type type{ctor::target_type::automatic};
ctor::output_system system{ctor::output_system::build};
std::string target; // Output target file for this configuration
ctor::sources sources; // source list
ctor::headers headers; // header list
+ ctor::extra_dist extra_dist; // extra files to be added to dist
std::vector<std::string> depends; // internal target dependencies
ctor::flags flags;
std::vector<std::string> externals; // externals used by this configuration
diff --git a/src/libctor.cc b/src/libctor.cc
index 2685ec0..6e6bcaf 100644
--- a/src/libctor.cc
+++ b/src/libctor.cc
@@ -16,6 +16,7 @@
#include <fstream>
#include <cstdlib>
#include <span>
+#include <set>
#include "ctor.h"
#include "configure.h"
@@ -26,6 +27,13 @@
#include "argparser.h"
#include "util.h"
+extern "C" {
+#include <archive.h>
+#include <archive_entry.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+}
+
int main(int argc, char* argv[])
{
auto args = std::span(argv, static_cast<std::size_t>(argc));
@@ -382,6 +390,122 @@ Options:
return ret;
}
}
+ else if(arg == "dist")
+ {
+ ctor::project project{};
+ std::set<std::string> dist_files;
+ auto& targets = getTargets(settings);
+ for(const auto& target : targets)
+ {
+ if(!target.config.project.name.empty())
+ {
+ project = target.config.project;
+ }
+
+ for(const auto& source : target.config.sources)
+ {
+ if(source.nodist)
+ {
+ continue;
+ }
+ std::filesystem::path p = target.path;
+ p /= source.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+ for(const auto& header : target.config.headers)
+ {
+ if(header.nodist)
+ {
+ continue;
+ }
+ std::filesystem::path p = target.path;
+ p /= header.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+ for(const auto& extra_dist_file : target.config.extra_dist)
+ {
+ if(extra_dist_file.nodist)
+ {
+ continue;
+ }
+ std::filesystem::path p = target.path;
+ p /= extra_dist_file.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+ }
+
+ const auto& configFiles = getConfigFileList();
+ for(const auto& configFile : configFiles)
+ {
+ std::filesystem::path p = configFile.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+
+ const auto& externalConfigFiles = getExternalConfigFileList();
+ for(const auto& externalConfigFile : externalConfigFiles)
+ {
+ std::filesystem::path p = externalConfigFile.file;
+ dist_files.insert(p.lexically_normal().string());
+ }
+
+ if(project.name.empty())
+ {
+ std::cerr << "Missing ctor::project description."
+ " Cannot create dist-file.\n";
+ return 1;
+ }
+ std::string outname = project.name + "-" +
+ std::to_string(project.version.major) + "." +
+ std::to_string(project.version.minor) + "." +
+ std::to_string(project.version.patch);
+ if(!project.version.tweak.empty())
+ {
+ outname += "-" + project.version.tweak;
+ }
+ outname += ".tar.gz";
+ {
+ struct archive *a;
+ struct archive_entry *entry;
+ struct stat st;
+ char buff[8192];
+ ssize_t len;
+ int fd;
+
+ a = archive_write_new();
+ // Filters: https://man.archlinux.org/man/archive_write_filter.3.en
+ archive_write_add_filter_gzip(a);
+ archive_write_set_format_pax_restricted(a); // Note 1
+ archive_write_open_filename(a, outname.data());
+
+ for(const auto& dist_file : dist_files)
+ {
+ const char*filename = dist_file.data();
+ stat(filename, &st);
+ auto mode = st.st_mode & 0xfff;//0644
+ std::cout << dist_file << std::oct << mode << '\n';
+ entry = archive_entry_new(); // Note 2
+ archive_entry_set_pathname(entry, filename);
+ archive_entry_set_size(entry, st.st_size); // Note 3
+ archive_entry_set_mtime(entry, st.st_mtime, 0);
+ archive_entry_set_filetype(entry, AE_IFREG);
+ archive_entry_set_perm(entry, mode);
+ archive_write_header(a, entry);
+ fd = open(filename, O_RDONLY);
+ len = read(fd, buff, sizeof(buff));
+ while ( len > 0 )
+ {
+ archive_write_data(a, buff, len);
+ len = read(fd, buff, sizeof(buff));
+ }
+ close(fd);
+ archive_entry_free(entry);
+ }
+
+ archive_write_close(a); // Note 4
+ archive_write_free(a); // Note 5
+ }
+ return 0;
+ }
else
{
build_all = false;
diff --git a/src/rebuild.cc b/src/rebuild.cc
index d62e998..30ca98e 100644
--- a/src/rebuild.cc
+++ b/src/rebuild.cc
@@ -156,6 +156,7 @@ bool recompileCheck(const ctor::settings& global_settings, int argc, char* argv[
config.flags.ldflags.emplace_back(ctor::ld_opt::library_path,
c.get(ctor::cfg::ctor_libdir));
}
+ config.flags.ldflags.emplace_back(ctor::ld_opt::link, "archive");
config.flags.ldflags.emplace_back(ctor::ld_opt::link, "ctor");
config.flags.ldflags.emplace_back(ctor::ld_opt::threads);
diff --git a/test/ctor.cc b/test/ctor.cc
index 6a86dc7..b18e3e7 100644
--- a/test/ctor.cc
+++ b/test/ctor.cc
@@ -31,7 +31,7 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
ctor::sources{
"generated_sources_test.cc",
"testmain.cc",
- "../configuration.cc",
+ {"../configuration.cc", ctor::nodist{}}
},
ctor::depends({"libctor_nomain.a"}),
ctor::cxx_flags{
@@ -90,6 +90,15 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
"-DOUTPUT=\"deps\"",
"-fexceptions",
},
+ ctor::extra_dist{
+ "deps_test_data/empty.d",
+ "deps_test_data/missing_colon.d",
+ "deps_test_data/multiline.d",
+ "deps_test_data/no_deps.d",
+ "deps_test_data/no_newline.d",
+ "deps_test_data/spaces.d",
+ "deps_test_data/trivial.d",
+ },
},
{
ctor::target_type::unit_test,
@@ -147,7 +156,7 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
ctor::sources{
"cycle_test.cc",
"testmain.cc",
- "../configuration.cc",
+ {"../configuration.cc", ctor::nodist{}}
},
ctor::depends({"libctor_nomain.a"}),
ctor::cxx_flags{
@@ -165,7 +174,7 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
ctor::sources{
"source_type_test.cc",
"testmain.cc",
- "../configuration.cc",
+ {"../configuration.cc", ctor::nodist{}}
},
ctor::depends({"libctor_nomain.a"}),
ctor::cxx_flags{
@@ -183,7 +192,7 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
ctor::sources{
"tools_test.cc",
"testmain.cc",
- "../configuration.cc",
+ {"../configuration.cc", ctor::nodist{}}
},
ctor::depends({"libctor_nomain.a"}),
ctor::cxx_flags{
@@ -218,6 +227,7 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
ctor::headers{
"paths.h",
"tmpfile.h",
+ "uunit/uunit.h",
},
ctor::cxx_flags{
"-std=c++20", "-O3", "-Wall",
@@ -225,6 +235,15 @@ ctor::build_configurations ctorTestConfigs(const ctor::settings& settings)
"-fexceptions",
},
ctor::ld_flags{ "-pthread" },
+ ctor::extra_dist{
+ "uunit/README",
+ "uunit/CC0-1.0",
+ "uunit/uunit.cc",
+ "uunit/examples/ExampleTest.cc",
+ "uunit/examples/Makefile",
+ "uunit/examples/getbaud.cc",
+ "uunit/examples/getbaud.h",
+ },
},
};
}