Moved from pkg-config to my lofi replica of csv

This commit is contained in:
Андреев Григорий 2024-08-16 22:22:27 +03:00
parent fe703a4c94
commit 4e6ca79e75
5 changed files with 161 additions and 60 deletions

2
.gitignore vendored
View File

@ -2,4 +2,4 @@
# Never use CMAKE in production
CMakeLists.txt
cmake-build-debug/
m.cpp

View File

@ -2,18 +2,33 @@ Build system for libregexis024
ABOUT
This is a build system in a form of header-only C++ library. It supports generation and installation of pkg-config files for your project.
This build system installs only two files:
1) header regexis024_build_system.h, that contains some useful functions for writing build scripts in C++
2) script regexis024_build_system.sh, that compiles a build script in your project (script invokes g++ with
-I flag pointing to regexis024_build_system.h installation dir)
INSTALLATION
You don't need to compile anything, this is a header-only library (more precisely, it is an only-one-file-kind library)
You don't need to compile anything, this is a header-only library
./install.sh [header installation path] [pkg-config file path]
./install.sh [installation root]
[header installation path] defaults to /usr/include
[pkg-config file path] defaults to /usr/lib/pkgconfig/regexis024-build-system.h
[installation root] by default is /usr
Files will be installed to
./include/regexis024_build_system.h and
./bin/regexis024_build_system.sh
HISTORY
One day I realized that make is a complete garbage, cmake is even worse, and shell scripting language is too hard to use to write anything complex.
I had to invent my own build system for my project libregexis024. But regexis024_build_system can be used for any other C++ project just fine.
One day I realized that make is a complete garbage, cmake is even worse, and shell scripting language is too hard to use
to write anything complex.
I had to invent my own build system for my project libregexis024. But regexis024_build_system can be used for any other
C++ project just fine.
Some time ago this build system was able to generate pkg-config .pc files for built libraries, but
for some reason pkg-config shuffled cflags on my friends pc, so I moved from pkg-config to my own, much simpler
library flags description format:
* For both cflags and linkage flags do this:
** For each argument do this:
*** escape " and \ symbols in argument and "tighten" result into double-quotes (a"\" c -> "a\"\\\" c")
** Concatenate results
* Join results by ;

View File

@ -1,32 +1,58 @@
#!/bin/sh
H_FILE="regexis024_build_system.h"
SH_TEMP_FILE="regexis024_build_system.sh"
if [ \! \( -f "$H_FILE" \) ]; then echo "Change cwd to root of build system source code root directory"; exit 1; fi
if [ \! \( -f "$H_FILE" \) -o \! \( -f "$SH_TEMP_FILE" \) ]; then
echo "Change cwd to root of build system source code root directory"; exit 1;
fi
usage(){
echo "Usage: ./install.sh [header installation dir path] [pkg-config file installation path]"
echo "Usage: ./install.sh [installation root]"
}
if [ $# -gt 2 ]; then usage; exit 1; fi
if [ $# -gt 1 ]; then usage; exit 1; fi
H_INST_DIR="/usr/include"
PC_INST_FILE="/usr/lib/pkgconfig/regexis024-build-system.pc"
INST_ROOT="/usr"
if [ $# -ge 1 ]; then H_INST_DIR="$1"; fi
if [ $# -ge 2 ]; then PC_INST_FILE="$2"; fi
if [ $# -ge 1 ]; then INST_ROOT="$1"; fi
cp "$H_FILE" "$H_INST_DIR/$H_FILE"
INST_ROOT="$(realpath "$INST_ROOT")"
if [ $? != 0 ]; then echo "Can't install"; exit 1; fi
install -d "$INST_ROOT/include"
echo "Name: regexis024-build-system" > "$PC_INST_FILE"
echo "Description: Cool C++ build system" >> "$PC_INST_FILE"
echo "Version: 1.0" >> "$PC_INST_FILE"
if [ $? != 0 ]; then
echo "Can't install IR/bin directory"; exit 1;
fi
COOL_FLAGS="-Wall -pedantic -Wno-unused-variable -Wno-unused-but-set-variable -Werror=return-type -Wno-reorder"
COOL_FLAGS="$COOL_FLAGS -D _GLIBCXX_DEBUG -D _POSIX_C_SOURCE=200809L"
COOL_FLAGS="$COOL_FLAGS -g --std c++14"
install "$H_FILE" "$INST_ROOT/include/"
echo "Cflags: $COOL_FLAGS -I $H_INST_DIR" >> "$PC_INST_FILE"
if [ $? != 0 ]; then
echo "Can't copy $H_FILE"; exit 1;
fi
I_DIR="$INST_ROOT/include"
escape4shell(){
echo "$1" | sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
}
SH_TEMPLATE="$(cat "$SH_TEMP_FILE")"
SH_TEMPLATE="${SH_TEMPLATE/"i_dir=99999"/"id_dir=$(escape4shell "$I_DIR")"}"
install -d "$INST_ROOT/bin"
if [ $? != 0 ]; then echo "Failed to install IR/bin directory"; exit 1; fi
echo "$SH_TEMPLATE" > "$INST_ROOT/bin/$SH_TEMP_FILE"
if [ $? != 0 ]; then
echo "Can't paste generated $SH_TEMP_FILE"; exit 1
fi
chmod +x "$INST_ROOT/bin/$SH_TEMP_FILE"
if [ $? != 0 ]; then
echo "Can't chmod +x on .sh script in IR/bin"; exit 1
fi

View File

@ -703,6 +703,51 @@ struct ExternalLibraryData {
std::vector<std::string> linkage_flags;
};
std::string lib_connection_flags_to_passed_forward_str(const ExternalLibraryData& lib) {
std::string result;
for (const std::string& f: lib.compilation_flags)
result += escape_with_doublequoting(f);
result += ";";
for (const std::string& f: lib.linkage_flags)
result += escape_with_doublequoting(f);
return result;
}
ExternalLibraryData parse_passed_forward_str(const std::string& str) {
ExternalLibraryData result;
int f = 0;
auto getOut = [&]() -> std::vector<std::string>& {
return f > 0 ? result.linkage_flags : result.compilation_flags;
};
bool in_str = false;
bool bsl = false;
for (char ch: str) {
if (in_str) {
if (bsl) {
bsl = false;
getOut().back() += ch;
} else if (ch == '\\') {
bsl = true;
} else if (ch == '"') {
in_str = false;
} else {
getOut().back() += ch;
}
} else if (ch == '"') {
in_str = true;
getOut().emplace_back();
} else if (ch == ';') {
f++;
if (f > 1)
THROW("PASSED_FORWARD.txt has only two fields: first - cflags; second - linking flags");
} else {
ASSERT(ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n',
"Only whitespaces can be between arguments in PASSED_FORWARD.txt")
}
}
return result;
}
struct ExternalLibraryTarget {
std::string name;
ExternalLibraryData data;
@ -727,9 +772,6 @@ struct CTarget {
std::vector<std::string> exported_headers;
std::string installation_dir;
/* If empty, no .pc file will be created. Otherwise, must include filename */
std::string pc_output_path;
std::string version = "0.1";
};
void check_is_good_name_1(const std::string& name) {
@ -741,7 +783,7 @@ void check_is_good_name_1(const std::string& name) {
void check_target_name(const std::string& name) {
check_is_good_name_1(name);
ASSERT(name != "obj", "DON'T YOU NEVER EVER CALL YOUR TARGET obj")
ASSERT(name != "obj" && name != "PASSED_FORWARD.txt", "DON'T YOU NEVER EVER CALL YOUR TARGET like this")
}
void check_is_clean_path_1(const path_t& path) {
@ -764,11 +806,6 @@ void check_c_unit_name(const path_t& P) {
ASSERT(P.parts.back().substr(ld) == ".cpp", "Right now only c++ is supported");
}
void check_pkg_conf_rel_install_path(const path_t& P) {
ASSERT_pl(P.is_relative && !P.parts.empty());
ASSERT_pl(does_str_end_in(P.parts.back(), ".pc"));
}
/* Argument `name` is just a name in `units` array, return value is relative to $IR/$TARGET_NAME/obj */
path_t c_unit_name_to_obj_filename(const std::string& PtoC) {
path_t P(PtoC);
@ -786,10 +823,6 @@ path_t c_unit_name_to_obj_filename(const std::string& PtoC) {
return P;
}
path_t c_unit_name_to_source_filename(const std::string& PtoC){
return path_t(PtoC);
}
void load_ctargets_on_building_and_installing(
const std::vector<ExternalLibraryTarget>& ext_lib_targs,
const std::vector<CTarget>& proj_targs,
@ -799,8 +832,7 @@ void load_ctargets_on_building_and_installing(
const std::string& proj_compiled_dir_path,
const std::string& install_include_dir_path,
const std::string& install_lib_dir_path,
const std::string& install_bin_dir_path,
const std::string& install_pkgconfig_dir_path)
const std::string& install_bin_dir_path)
{
std::map<std::string, ExternalLibraryData> ext_libs_map;
for (auto& e: ext_lib_targs) {
@ -813,7 +845,7 @@ void load_ctargets_on_building_and_installing(
size_t end_BBU_id;
/* Main build unit of target in "install" runlevel */
size_t end_IBU_id;
/* When this ctarget is used as dependency, these flags should be used aquire my ctarget as dependency */
/* When this ctarget is used as dependency, these flags should be used to aquire my ctarget as dependency */
std::vector<std::string> emitted_compilation_flags_USED_HERE;
std::vector<std::string> emitted_compilation_flags_PASSED_FORWARD;
std::vector<std::string> emitted_linkage_flags_USED_HERE;
@ -843,13 +875,13 @@ void load_ctargets_on_building_and_installing(
size_t mk_personal_targ_dir_bu_id = add_bbu(new MkdirBuildUnit(path_t(proj_compiled_dir_path) / tg.name));
std::vector<size_t> all_comp_units_bu_ids;
auto BU_to_SOURCE_FILEPATH = [&](const std::string& bu) -> path_t {
return path_t(proj_src_dir_path) / c_unit_name_to_source_filename(bu);
return path_t(proj_src_dir_path) / bu;
};
auto BU_to_OBJ_FILEPATH = [&](const std::string& bu) -> path_t {
return path_t(proj_compiled_dir_path) / tg.name / "obj" / c_unit_name_to_obj_filename(bu);
};
auto generate_cu_BUs = [&](const std::vector<std::string>& ctg_type_intrinsic_comp_args) {
const std::string comp_cmd = "g++"; // todo: think of some other way around
const std::string comp_cmd = "g++"; // todo: *speaks in soydev voice* AAAA OOOO AAA I LOVE GCC
for (const std::string& bu: tg.units) {
check_c_unit_name(bu);
path_t buDir = bu;
@ -944,7 +976,6 @@ void load_ctargets_on_building_and_installing(
if (tg.type == "executable") {
ASSERT(tg.exported_headers.empty(), "C-target's field `exported_headers` is unsupported for type `executable`");
ASSERT(tg.include_ir.empty(), "C-target's field `include_ir` is unsupported for type `executable`");
ASSERT(tg.pc_output_path.empty(), "C-target's field `pc_output_path` is unsupported for type `executable`");
generate_cu_BUs({});
generate_targ_link_BU({}, "");
gen_ibus_for_this_th(install_bin_dir_path, "");
@ -987,19 +1018,13 @@ void load_ctargets_on_building_and_installing(
"-Wl,-rpath," + install_lib_dir_path + "/" + tg.installation_dir,
"-l:" + tg.name + ".so"
});
/* Determining how to create pkg-config file at installation stage */
if (!tg.pc_output_path.empty()) {
check_pkg_conf_rel_install_path(tg.pc_output_path);
// todo: ESCAPE THESE VALUES
size_t pkg_conf_install_ibu = add_ibu(new FileWriteBuildUnit(
path_t(install_pkgconfig_dir_path) / tg.pc_output_path,
"Name: " + tg.name + "\n" +
"Description: \n" +
"Version: " + tg.version + "\n" +
"Cflags: " + join_string_arr(s.emitted_compilation_flags_PASSED_FORWARD, " ") + "\n" +
"Libs: " + join_string_arr(s.emitted_linkage_flags_PASSED_FORWARD, " ") + "\n"));
ret_at_install[blank_ibu_for_tg_FINAL]->bu_dependencies.push_back(pkg_conf_install_ibu);
}
size_t PASSED_FORWARD_file_ibu = add_ibu(new FileWriteBuildUnit(
path_t(proj_compiled_dir_path) / tg.name / "PASSED_FORWARD.txt",
lib_connection_flags_to_passed_forward_str(ExternalLibraryData{
s.emitted_compilation_flags_PASSED_FORWARD,
s.emitted_linkage_flags_PASSED_FORWARD
})));
ret_at_install[blank_ibu_for_tg_FINAL]->bu_dependencies.push_back(PASSED_FORWARD_file_ibu);
/* s.end_BU... fields allow us to establish dependency relations between BUs of ctargets with such relation */
s.end_BBU_id = targ_FINAL_bbu_id;
s.end_IBU_id = blank_ibu_for_tg_FINAL;
@ -1061,7 +1086,6 @@ const char* default_PR_postf_built_compiled = "/built/compiled";
const char* default_IR_postf_include = "/include";
const char* default_IR_postf_lib = "/lib";
const char* default_IR_postf_bin = "/bin";
const char* default_IR_postf_pkgconfig = "/lib/pkgconfig";
void regular_bs_cli_cmd_interpret(const std::vector<std::string>& args, NormalCBuildSystemCommandMeaning& reta) {
normal_c_build_system_command_interpret(args, reta, default_PR_postf_built_local_install);
@ -1078,9 +1102,9 @@ void regular_ctargets_to_2bus_conversion(
project_root + default_PR_postf_built_compiled,
installation_root + default_IR_postf_include,
installation_root + default_IR_postf_lib,
installation_root + default_IR_postf_bin,
installation_root + default_IR_postf_pkgconfig
installation_root + default_IR_postf_bin
);
}
#endif //REGEXIS024_BUILD_SYSTEM_H
#endif

36
regexis024_build_system.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/sh
i_dir=99999
flags="-Wall -Wextra -pedantic -Wno-unused-variable -Wno-unused-but-set-variable -Werror=return-type -Wno-reorder -Wno-missing-field-initializers"
flags="$flags -g --std c++14 -D _GLIBCXX_DEBUG"
usage(){
echo "Usage: regexis024_build_system.sh [bs script (cpp file)]"
}
if [ $# -gt 1 ]; then usage; exit 1; fi
SCRIPT="./building/main.cpp"
is_cpp(){
case "$1" in *.cpp) true;; *) false;; esac;
}
if [ $# -ge 1 ]; then
SCRIPT="$1"
fi
if [ \! \( -f "$SCRIPT" \) ]; then
echo "No such file $SCRIPT"; exit 1;
fi
if ! is_cpp "$SCRIPT"; then
echo "Script file does not end in .cpp"; exit 1
fi
# Todo: rewrite with sed
COMPILED="${SCRIPT%.cpp}"
g++ $flags -I "$i_dir" -o "$COMPILED" "$SCRIPT"