Moved from pkg-config to my lofi replica of csv
This commit is contained in:
parent
fe703a4c94
commit
4e6ca79e75
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,4 +2,4 @@
|
|||||||
# Never use CMAKE in production
|
# Never use CMAKE in production
|
||||||
CMakeLists.txt
|
CMakeLists.txt
|
||||||
cmake-build-debug/
|
cmake-build-debug/
|
||||||
|
m.cpp
|
29
README.txt
29
README.txt
@ -2,18 +2,33 @@ Build system for libregexis024
|
|||||||
|
|
||||||
ABOUT
|
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
|
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
|
[installation root] by default is /usr
|
||||||
[pkg-config file path] defaults to /usr/lib/pkgconfig/regexis024-build-system.h
|
Files will be installed to
|
||||||
|
./include/regexis024_build_system.h and
|
||||||
|
./bin/regexis024_build_system.sh
|
||||||
|
|
||||||
HISTORY
|
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.
|
One day I realized that make is a complete garbage, cmake is even worse, and shell scripting language is too hard to use
|
||||||
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.
|
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 ;
|
||||||
|
58
install.sh
58
install.sh
@ -1,32 +1,58 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
H_FILE="regexis024_build_system.h"
|
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(){
|
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"
|
INST_ROOT="/usr"
|
||||||
PC_INST_FILE="/usr/lib/pkgconfig/regexis024-build-system.pc"
|
|
||||||
|
|
||||||
if [ $# -ge 1 ]; then H_INST_DIR="$1"; fi
|
if [ $# -ge 1 ]; then INST_ROOT="$1"; fi
|
||||||
if [ $# -ge 2 ]; then PC_INST_FILE="$2"; 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"
|
if [ $? != 0 ]; then
|
||||||
echo "Description: Cool C++ build system" >> "$PC_INST_FILE"
|
echo "Can't install IR/bin directory"; exit 1;
|
||||||
echo "Version: 1.0" >> "$PC_INST_FILE"
|
fi
|
||||||
|
|
||||||
COOL_FLAGS="-Wall -pedantic -Wno-unused-variable -Wno-unused-but-set-variable -Werror=return-type -Wno-reorder"
|
install "$H_FILE" "$INST_ROOT/include/"
|
||||||
COOL_FLAGS="$COOL_FLAGS -D _GLIBCXX_DEBUG -D _POSIX_C_SOURCE=200809L"
|
|
||||||
COOL_FLAGS="$COOL_FLAGS -g --std c++14"
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
@ -703,6 +703,51 @@ struct ExternalLibraryData {
|
|||||||
std::vector<std::string> linkage_flags;
|
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 {
|
struct ExternalLibraryTarget {
|
||||||
std::string name;
|
std::string name;
|
||||||
ExternalLibraryData data;
|
ExternalLibraryData data;
|
||||||
@ -727,9 +772,6 @@ struct CTarget {
|
|||||||
std::vector<std::string> exported_headers;
|
std::vector<std::string> exported_headers;
|
||||||
|
|
||||||
std::string installation_dir;
|
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) {
|
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) {
|
void check_target_name(const std::string& name) {
|
||||||
check_is_good_name_1(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) {
|
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");
|
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 */
|
/* 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 c_unit_name_to_obj_filename(const std::string& PtoC) {
|
||||||
path_t P(PtoC);
|
path_t P(PtoC);
|
||||||
@ -786,10 +823,6 @@ path_t c_unit_name_to_obj_filename(const std::string& PtoC) {
|
|||||||
return P;
|
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(
|
void load_ctargets_on_building_and_installing(
|
||||||
const std::vector<ExternalLibraryTarget>& ext_lib_targs,
|
const std::vector<ExternalLibraryTarget>& ext_lib_targs,
|
||||||
const std::vector<CTarget>& proj_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& proj_compiled_dir_path,
|
||||||
const std::string& install_include_dir_path,
|
const std::string& install_include_dir_path,
|
||||||
const std::string& install_lib_dir_path,
|
const std::string& install_lib_dir_path,
|
||||||
const std::string& install_bin_dir_path,
|
const std::string& install_bin_dir_path)
|
||||||
const std::string& install_pkgconfig_dir_path)
|
|
||||||
{
|
{
|
||||||
std::map<std::string, ExternalLibraryData> ext_libs_map;
|
std::map<std::string, ExternalLibraryData> ext_libs_map;
|
||||||
for (auto& e: ext_lib_targs) {
|
for (auto& e: ext_lib_targs) {
|
||||||
@ -813,7 +845,7 @@ void load_ctargets_on_building_and_installing(
|
|||||||
size_t end_BBU_id;
|
size_t end_BBU_id;
|
||||||
/* Main build unit of target in "install" runlevel */
|
/* Main build unit of target in "install" runlevel */
|
||||||
size_t end_IBU_id;
|
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_USED_HERE;
|
||||||
std::vector<std::string> emitted_compilation_flags_PASSED_FORWARD;
|
std::vector<std::string> emitted_compilation_flags_PASSED_FORWARD;
|
||||||
std::vector<std::string> emitted_linkage_flags_USED_HERE;
|
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));
|
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;
|
std::vector<size_t> all_comp_units_bu_ids;
|
||||||
auto BU_to_SOURCE_FILEPATH = [&](const std::string& bu) -> path_t {
|
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 {
|
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);
|
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) {
|
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) {
|
for (const std::string& bu: tg.units) {
|
||||||
check_c_unit_name(bu);
|
check_c_unit_name(bu);
|
||||||
path_t buDir = bu;
|
path_t buDir = bu;
|
||||||
@ -944,7 +976,6 @@ void load_ctargets_on_building_and_installing(
|
|||||||
if (tg.type == "executable") {
|
if (tg.type == "executable") {
|
||||||
ASSERT(tg.exported_headers.empty(), "C-target's field `exported_headers` is unsupported for 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.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_cu_BUs({});
|
||||||
generate_targ_link_BU({}, "");
|
generate_targ_link_BU({}, "");
|
||||||
gen_ibus_for_this_th(install_bin_dir_path, "");
|
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,
|
"-Wl,-rpath," + install_lib_dir_path + "/" + tg.installation_dir,
|
||||||
"-l:" + tg.name + ".so"
|
"-l:" + tg.name + ".so"
|
||||||
});
|
});
|
||||||
/* Determining how to create pkg-config file at installation stage */
|
size_t PASSED_FORWARD_file_ibu = add_ibu(new FileWriteBuildUnit(
|
||||||
if (!tg.pc_output_path.empty()) {
|
path_t(proj_compiled_dir_path) / tg.name / "PASSED_FORWARD.txt",
|
||||||
check_pkg_conf_rel_install_path(tg.pc_output_path);
|
lib_connection_flags_to_passed_forward_str(ExternalLibraryData{
|
||||||
// todo: ESCAPE THESE VALUES
|
s.emitted_compilation_flags_PASSED_FORWARD,
|
||||||
size_t pkg_conf_install_ibu = add_ibu(new FileWriteBuildUnit(
|
s.emitted_linkage_flags_PASSED_FORWARD
|
||||||
path_t(install_pkgconfig_dir_path) / tg.pc_output_path,
|
})));
|
||||||
"Name: " + tg.name + "\n" +
|
ret_at_install[blank_ibu_for_tg_FINAL]->bu_dependencies.push_back(PASSED_FORWARD_file_ibu);
|
||||||
"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);
|
|
||||||
}
|
|
||||||
/* s.end_BU... fields allow us to establish dependency relations between BUs of ctargets with such relation */
|
/* 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_BBU_id = targ_FINAL_bbu_id;
|
||||||
s.end_IBU_id = blank_ibu_for_tg_FINAL;
|
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_include = "/include";
|
||||||
const char* default_IR_postf_lib = "/lib";
|
const char* default_IR_postf_lib = "/lib";
|
||||||
const char* default_IR_postf_bin = "/bin";
|
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) {
|
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);
|
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,
|
project_root + default_PR_postf_built_compiled,
|
||||||
installation_root + default_IR_postf_include,
|
installation_root + default_IR_postf_include,
|
||||||
installation_root + default_IR_postf_lib,
|
installation_root + default_IR_postf_lib,
|
||||||
installation_root + default_IR_postf_bin,
|
installation_root + default_IR_postf_bin
|
||||||
installation_root + default_IR_postf_pkgconfig
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //REGEXIS024_BUILD_SYSTEM_H
|
#endif
|
||||||
|
|
||||||
|
36
regexis024_build_system.sh
Executable file
36
regexis024_build_system.sh
Executable 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"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user