From 1af138308d01f96dd979f0137394dcbd5971d5e1 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Tue, 10 Feb 2026 19:38:36 +0100 Subject: WIP: install --- ctor.cc | 3 +- src/argparser.h | 10 +++++ src/bootstrap.cc | 7 +++- src/configure.cc | 113 ++++++++++++++++++++++++++++++++++++++++++++++++------ src/ctor.h | 52 ++++++++++++++++++++++++- src/libctor.cc | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/util.cc | 10 +++++ 7 files changed, 292 insertions(+), 17 deletions(-) diff --git a/ctor.cc b/ctor.cc index f485309..cab0484 100644 --- a/ctor.cc +++ b/ctor.cc @@ -13,6 +13,7 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings) ctor::project{"libctor", {1,0,0, "rc1"}}, ctor::output_system::build, ctor::target("libctor.a"), + ctor::install{}, ctor::sources{ "src/build.cc", "src/configure.cc", @@ -37,7 +38,7 @@ ctor::build_configurations ctorConfigs(const ctor::settings& settings) "src/argparser.h", "src/build.h", "src/configure.h", - "src/ctor.h", + {"src/ctor.h", ctor::install{}}, "src/deps.h", "src/execute.h", "src/externals.h", diff --git a/src/argparser.h b/src/argparser.h index c5337e0..8f1ef39 100644 --- a/src/argparser.h +++ b/src/argparser.h @@ -237,6 +237,11 @@ public: options.emplace_back(Opt{shortopt, longopt, cb, help}); } + void add(const std::string& caption) + { + options.emplace_back(Opt{{}, {}, {}, caption}); + } + void set_pos_cb(std::function cb) { pos_cb = cb; @@ -270,6 +275,11 @@ public: using T = std::decay_t; if constexpr (std::is_same_v>) { + if(opt.longopt.empty()) + { + std::cout << "\n" << opt.help << ":\n"; + return; + } } else if constexpr (std::is_same_v>) { diff --git a/src/bootstrap.cc b/src/bootstrap.cc index 1ab4f31..4174edc 100644 --- a/src/bootstrap.cc +++ b/src/bootstrap.cc @@ -116,12 +116,15 @@ int main(int argc, char* argv[]) } ctor::settings settings{}; - const auto& c = ctor::get_configuration(); settings.builddir = c.get(ctor::cfg::builddir, settings.builddir); settings.parallel_processes = std::max(1u, std::thread::hardware_concurrency() * 2 - 1); - settings.verbose = 1; + auto V = std::getenv("V"); + if(V && std::string(V) == "1") + { + settings.verbose = 1; + } auto all_tasks = getTasks(settings, {}, false); for(auto task : all_tasks) { diff --git a/src/configure.cc b/src/configure.cc index 5ba87c3..3a4abd4 100644 --- a/src/configure.cc +++ b/src/configure.cc @@ -286,6 +286,39 @@ int regenerateCache(ctor::settings& settings, std::string ctor_libdir; std::string builddir; + // Installation directories: + std::string prefix = "/usr/local"; + std::string exec_prefix;//install architecture-dependent files in EPREFIX + + // Fine tuning of the installation directories: + std::string bindir;// user executables [EPREFIX/bin] + std::string sbindir;// system admin executables [EPREFIX/sbin] + std::string libexecdir;// program executables [EPREFIX/libexec] + std::string sysconfdir;// read-only single-machine data [PREFIX/etc] + std::string sharedstatedir;// modifiable architecture-independent data [PREFIX/com] + std::string localstatedir;// modifiable single-machine data [PREFIX/var] + std::string runstatedir;// modifiable per-process data [LOCALSTATEDIR/run] + // object code libraries [EPREFIX/lib] + std::string libdir; + // C header files [PREFIX/include] + std::string includedir; + std::string oldincludedir;//C header files for non-gcc [/usr/include] + std::string datarootdir;// read-only arch.-independent data root [PREFIX/share] + std::string datadir;// read-only architecture-independent data [DATAROOTDIR] + std::string infodir;// info documentation [DATAROOTDIR/info] + std::string localedir;// locale-dependent data [DATAROOTDIR/locale] + std::string mandir;// man documentation [DATAROOTDIR/man] + std::string docdir;// documentation root [DATAROOTDIR/doc/drumgizmo] + std::string htmldir;// html documentation [DOCDIR] + std::string dvidir;// dvi documentation [DOCDIR] + std::string pdfdir;// pdf documentation [DOCDIR] + std::string psdir;// ps documentation [DOCDIR] + + //Program names: + std::string program_prefix;// prepend PREFIX to installed program names + std::string program_suffix;// append SUFFIX to installed program names + std::string program_transform_name;//run sed PROGRAM on installed program names + opt.add('b', "--build-dir", std::function([&](std::string arg) { @@ -384,6 +417,75 @@ int regenerateCache(ctor::settings& settings, }), "Set path to ctor library file, used for re-compiling."); + opt.add('h', "--help", + std::function([&]() -> int + { + std::cout << "Configure how to build with " << name << "\n"; + std::cout << "Usage: " << name << " configure [options]\n\n"; + std::cout << "Options:\n"; + opt.help(); + exit(0); + }), + "Print this help text."); +/* +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [/usr/local] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, `make install' will install all the files in +`/usr/local/bin', `/usr/local/lib' etc. You can specify +an installation prefix other than `/usr/local' using `--prefix', +for instance `--prefix=$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/drumgizmo] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + */ + opt.add("Installation directories"); + + opt.add({}, "--prefix", + std::function([&](std::string arg) + { + prefix = arg; + return 0; + }), + "Install architecture-independent files in (" + prefix + ")."); + +// opt.add({}, "--exec-prefix", +// std::function([&](std::string arg) +// { +// exec_prefix = arg; +// return 0; +// }), +// "Install architecture-dependent files in (" + prefix + ")."); + // Resolv externals ctor::external_configurations externalConfigs; const auto& externalConfigFiles = getExternalConfigFileList(); @@ -432,17 +534,6 @@ int regenerateCache(ctor::settings& settings, } - opt.add('h', "--help", - std::function([&]() -> int - { - std::cout << "Configure how to build with " << name << "\n"; - std::cout << "Usage: " << name << " configure [options]\n\n"; - std::cout << "Options:\n"; - opt.help(); - exit(0); - }), - "Print this help text."); - opt.set_err_cb( [&](arg::error err, std::string_view arg) { diff --git a/src/ctor.h b/src/ctor.h index 665ab75..9c00225 100644 --- a/src/ctor.h +++ b/src/ctor.h @@ -80,6 +80,48 @@ struct nodist bool value{true}; }; +enum class install_type +{ + automatic, // Deduced from target-type + program, + library, + header, + // man, ... +}; + +/// Indicate that this target should be part of install target +struct install +{ + template + requires (( + std::is_same_v || + std::is_same_v || + std::is_convertible_v + ) && ...) + constexpr install(Args && ... arg) + { + do_install = true; + ([&] + { + if constexpr(std::is_same_v) + { + do_install = arg; + } + else if constexpr(std::is_same_v) + { + type = arg; + } + else if constexpr(std::is_convertible_v) + { + path = arg; + } + }(), ...); + } + ctor::install_type type{ctor::install_type::automatic}; + std::string path; // Default: Install dir for type (bin, lib, include, ...) + bool do_install{false}; +}; + struct source { template @@ -137,7 +179,8 @@ struct header template requires (( std::is_convertible_v || - std::is_same_v + std::is_same_v || + std::is_same_v ) && ...) constexpr header(Args && ... arg) { @@ -156,6 +199,7 @@ struct header std::string file; bool nodist{false}; + ctor::install install{false}; }; using headers = std::vector; @@ -448,6 +492,7 @@ struct build_configuration std::is_same_v || std::is_same_v || std::is_same_v || + std::is_same_v || std::is_same_v || std::is_convertible_v || std::is_convertible_v || @@ -497,6 +542,10 @@ struct build_configuration { depends = arg.depends; } + else if constexpr(std::is_same_v) + { + install = arg; + } else if constexpr(std::is_same_v) { externals = arg.externals; @@ -545,6 +594,7 @@ struct build_configuration std::vector externals; // externals used by this configuration ctor::GeneratorOneToOne function_one_to_one; ctor::GeneratorManyToOne function_many_to_one; + ctor::install install{false}; }; using build_configurations = std::vector; diff --git a/src/libctor.cc b/src/libctor.cc index 6e6bcaf..230662a 100644 --- a/src/libctor.cc +++ b/src/libctor.cc @@ -66,6 +66,7 @@ int main(int argc, char* argv[]) bool list_targets{false}; bool no_relaunch{false}; // true means no re-launch after rebuild. bool run_unittests{false}; + bool install{false}; std::vector arguments; arg::Parser opt(argc, argv); opt.set_pos_cb( @@ -504,7 +505,11 @@ Options: archive_write_close(a); // Note 4 archive_write_free(a); // Note 5 } - return 0; + } + else if(arg == "install") + { + install = true; + build_all = true; } else { @@ -562,7 +567,112 @@ Options: if(run_unittests) { - return runUnitTests(all_tasks, settings); + auto ret = runUnitTests(all_tasks, settings); + if(ret != 0) + { + return ret; + } + } + + if(install) + { + auto destdir_env = std::getenv("DESTDIR"); + if(!destdir_env) + { + std::cerr << "No DESTDIR provided!\n"; + return 1; + } + std::filesystem::path destdir = destdir_env; + if(!destdir.is_absolute()) + { + std::cerr << "DESTDIR must be absolute!\n"; + return 1; + } + std::cout << "Installing in DESTDIR: " << destdir.string() << "\n"; + std::string prefix = "/usr"; + for(const auto& task : all_tasks) + { + auto install_target = task->buildConfig().install; + if(!task->derived() && install_target.do_install) + { + std::string target_dir{}; + if(!install_target.path.empty()) + { + target_dir = install_target.path; + } + else + { + switch(task->targetType()) + { + case ctor::target_type::unit_test: + case ctor::target_type::unit_test_library: + case ctor::target_type::object: + case ctor::target_type::function: + case ctor::target_type::automatic: + case ctor::target_type::unknown: + // Ignore + continue; + break; + case ctor::target_type::executable: + target_dir = "bin"; + break; + case ctor::target_type::shared_library: + case ctor::target_type::static_library: + case ctor::target_type::module: + target_dir = "lib"; + break; + } + } + std::filesystem::path target; + target = prefix; + target /= target_dir; + target /= task->target(); + if(destdir_env) + { + if(target.is_absolute()) + { + target = destdir / target.relative_path(); + } + else + { + target = destdir / target; + } + } + std::cout << "Bin install " << task->target() << + " -> " << target.string() << "\n"; + } + } + + auto& targets = getTargets(settings); + for(const auto& target : targets) + { + for(const auto& header : target.config.headers) + { + if(header.install.do_install) + { + std::filesystem::path target_file = prefix; + target_file /= "include"; + if(!header.install.path.empty()) + { + target_file /= header.install.path; + } + target_file /= std::filesystem::path(header.file).filename(); + if(destdir_env) + { + if(target_file.is_absolute()) + { + target_file = destdir / target_file.relative_path(); + } + else + { + target_file = destdir / target_file; + } + } + std::cout << "Include/header install " << header.file << + " -> " << target_file.string() << "\n"; + } + } + } } return 0; diff --git a/src/util.cc b/src/util.cc index 7ca9c11..0655dfa 100644 --- a/src/util.cc +++ b/src/util.cc @@ -71,6 +71,16 @@ ctor::language languageFromExtension(const std::filesystem::path& file) return ctor::language::assembler; } +// if(ext == ".h" || +// ext == ".hh" || +// ext == ".hpp" || +// ext == ".hxx" || +// ext == ".tpp" || +// ext == ".ipp") +// { +// return ctor::language::header; +// } + std::cerr << "Could not deduce language from " << file.string() << "\n"; exit(1); return {}; -- cgit v1.2.3