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
|
||||
CMakeLists.txt
|
||||
cmake-build-debug/
|
||||
|
||||
m.cpp
|
29
README.txt
29
README.txt
@ -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 ;
|
||||
|
58
install.sh
58
install.sh
@ -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
|
||||
|
||||
|
@ -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
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