Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59efef4b07 | ||
|
|
7f3794e742 | ||
|
|
370995978c | ||
|
|
9dc9f158fe | ||
|
|
03efe5c7c0 | ||
|
|
0264245411 | ||
|
|
e03dbf9e7a | ||
|
|
a54f50a65a | ||
|
|
8e172ba1cc | ||
|
|
0a5af1f757 |
@@ -13,7 +13,8 @@ const char* CXX = "c++";
|
||||
#define DEBUG_FLAGS "-g"
|
||||
|
||||
// ...when not debugging
|
||||
#define RELEASE_FLAGS "-Ofast", "-s"
|
||||
// -O2 seems to work best for both execution and compilation speed
|
||||
#define RELEASE_FLAGS "-O2", "-s"
|
||||
|
||||
// ...for both C and C++
|
||||
#define CPPFLAGS "-fwhole-program", "-march=native", "-Wall", "-Wextra", "-pipe"
|
||||
|
||||
+1
-2
@@ -13,8 +13,7 @@ chmod 755 cppipe
|
||||
mv cppipe ${PREFIX}/bin
|
||||
|
||||
# Install headers
|
||||
mkdir -p ${PREFIX}/include/cppipe
|
||||
chmod 755 ${PREFIX}/include/cppipe
|
||||
mkdir -p -m755 ${PREFIX}/include/cppipe
|
||||
cp basicTypes.h commands.hpp commands.inl childProcess.hpp childProcess.inl ${PREFIX}/include/cppipe
|
||||
chmod 644 ${PREFIX}/include/cppipe/*
|
||||
|
||||
|
||||
+4
-3
@@ -2,10 +2,11 @@
|
||||
set -e
|
||||
|
||||
# Test cppipe functions
|
||||
OKs=$(test/functions_test.cppipe 2>/dev/null | grep OK | wc -l)
|
||||
if ! [ $OKs = 13 ]
|
||||
OKs=$(test/functions_test.cppipe | grep OK | wc -l)
|
||||
EXPECTED=14
|
||||
if ! [ $OKs = $EXPECTED ]
|
||||
then
|
||||
echo "Functions test failed: EXPECTED 13 OKs, got $OKs"
|
||||
echo "Functions test failed: EXPECTED $EXPECTED OKs, got $OKs"
|
||||
exit 1
|
||||
fi
|
||||
echo Functions test OK!
|
||||
|
||||
+10
-9
@@ -18,11 +18,11 @@ class Cmd
|
||||
public:
|
||||
/* all args must be const char* */
|
||||
template<typename... Args>
|
||||
explicit Cmd(Args... args)
|
||||
: argv({args...})
|
||||
{
|
||||
argv.push_back(nullptr);
|
||||
}
|
||||
explicit Cmd(Args...);
|
||||
|
||||
/* Implicitly convert from { "command", "param" }
|
||||
* e.g: exec({ "cmd", "arg" }); */
|
||||
Cmd(std::initializer_list<const char*> args);
|
||||
|
||||
/* Execute the command, if arguments are not given use stdin,out,err
|
||||
else use the given file desciptors. this can also be used
|
||||
@@ -45,8 +45,9 @@ public:
|
||||
class PendingCmd
|
||||
{
|
||||
public:
|
||||
PendingCmd(std::initializer_list<const char*> cmd_args);
|
||||
/* Can be implicitly created from a command */
|
||||
PendingCmd(const Cmd&, fd_t in=0, fd_t out=1, fd_t err=2);
|
||||
PendingCmd(Cmd, fd_t in=0, fd_t out=1, fd_t err=2);
|
||||
/* Execute the command on destruction */
|
||||
~PendingCmd();
|
||||
|
||||
@@ -60,10 +61,10 @@ public:
|
||||
/* Prevent a pending command from being executed on destruction */
|
||||
void cancel();
|
||||
|
||||
const Cmd& cmd;
|
||||
fd_t in, out, err;
|
||||
Cmd cmd;
|
||||
fd_t in=0, out=1, err=2;
|
||||
private:
|
||||
bool execed_;
|
||||
bool execed_ = false;
|
||||
|
||||
friend Proc detach(const PendingCmd&);
|
||||
friend Proc detachRedirIn(const PendingCmd&);
|
||||
|
||||
+20
-3
@@ -28,6 +28,18 @@ namespace _cppipe
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline Cmd::Cmd(Args... args)
|
||||
: Cmd({ args... })
|
||||
{
|
||||
}
|
||||
|
||||
inline Cmd::Cmd(std::initializer_list<const char*> args)
|
||||
: argv(args)
|
||||
{
|
||||
argv.push_back(nullptr);
|
||||
}
|
||||
|
||||
inline DeadProc Cmd::operator()(fd_t in, fd_t out, fd_t err) const
|
||||
{
|
||||
Proc p = createProcess(argv.data(), in, out, err);
|
||||
@@ -58,13 +70,18 @@ inline Cmd& Cmd::operator+=(const char* arg)
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PendingCmd::PendingCmd(std::initializer_list<const char*> cmd_args)
|
||||
: cmd(cmd_args)
|
||||
, in(0)
|
||||
, out(1)
|
||||
, err(2)
|
||||
{}
|
||||
|
||||
inline PendingCmd::PendingCmd(const Cmd& origin, fd_t in, fd_t out, fd_t err)
|
||||
: cmd(origin)
|
||||
inline PendingCmd::PendingCmd(Cmd origin, fd_t in, fd_t out, fd_t err)
|
||||
: cmd(std::move(origin))
|
||||
, in(in)
|
||||
, out(out)
|
||||
, err(err)
|
||||
, execed_(false)
|
||||
{}
|
||||
|
||||
inline PendingCmd::~PendingCmd()
|
||||
|
||||
+46
-11
@@ -60,7 +60,6 @@ SrcType find_src_type(string_view path);
|
||||
const char DEBUG_PREFIX[] = "__DBG";
|
||||
|
||||
// Context
|
||||
fs::path HOME;
|
||||
fs::path src_file;
|
||||
SrcType src_type;
|
||||
fs::path cache_dir;
|
||||
@@ -71,6 +70,9 @@ fs::path bin; // cache bins to avoid recompiles
|
||||
bool debug = false;
|
||||
// just compare timestamps of the source and bin, don't preprocess
|
||||
bool quick = false;
|
||||
// Just compile, don't run
|
||||
bool dont_run = false;
|
||||
vector<const char*> additional_compiler_args;
|
||||
|
||||
}
|
||||
|
||||
@@ -79,7 +81,6 @@ int main(int argc, char* argv[])
|
||||
int src_arg = parse_args_until_src(argc, argv);
|
||||
|
||||
// Init context
|
||||
HOME = getenv("HOME");
|
||||
src_file = find_path_to_src( argv[src_arg] );
|
||||
src_type = find_src_type( argv[src_arg] );
|
||||
cache_dir = get_cache_dir_path(src_file);
|
||||
@@ -93,6 +94,9 @@ int main(int argc, char* argv[])
|
||||
compile_src_file();
|
||||
|
||||
// Run the src file without forking
|
||||
if(dont_run)
|
||||
return 0;
|
||||
|
||||
Cmd run;
|
||||
if(debug) // debug it with gdb
|
||||
{
|
||||
@@ -103,6 +107,7 @@ int main(int argc, char* argv[])
|
||||
run += bin.c_str();
|
||||
for(int i = src_arg+1; i < argc; ++i)
|
||||
run += argv[i];
|
||||
|
||||
exec(run);
|
||||
}
|
||||
|
||||
@@ -125,11 +130,16 @@ int parse_args_until_src(int argc, char* argv[])
|
||||
{
|
||||
print_usage();
|
||||
cout << "Compile and run C/C++ source FILE\n"
|
||||
"Pass the ARGUMENTS to the compiled binary\n"
|
||||
"Pass the ARGUMENT to the compiled binary\n"
|
||||
"The binaries are cached and recompiled only if the source or it's headers have changed\n\n"
|
||||
"Options:\n"
|
||||
"-g debug the binary, asserts are also enabled\n"
|
||||
"-q quicker, just compare source and binary time stamps, if included files were updated a recompile WON'T occur!\n\n"
|
||||
"-q quicker, just compare source and binary time stamps, if included files were updated a recompile WON'T occur!\n"
|
||||
"-n don't run, just compile the file without running it\n\n"
|
||||
|
||||
"Any other argument that begins with '-' is passed to the compiler e.g.:\n"
|
||||
" cppipe -O0 file.cpp\n\n"
|
||||
|
||||
"Environment variables:\n"
|
||||
"CPPIPEPATH - ':'-separated list of directories to prepend to the FILE search path\n";
|
||||
exit(0);
|
||||
@@ -142,6 +152,14 @@ int parse_args_until_src(int argc, char* argv[])
|
||||
{
|
||||
quick = true;
|
||||
}
|
||||
else if( arg == "-n" )
|
||||
{
|
||||
dont_run = true;
|
||||
}
|
||||
else if( !arg.empty() && arg[0] == '-') // if it's an unknown option pass it to the compiler
|
||||
{
|
||||
additional_compiler_args.push_back(argv[i]);
|
||||
}
|
||||
else // Then treat it as the src_arg
|
||||
{
|
||||
src_arg = i;
|
||||
@@ -191,14 +209,19 @@ fs::path find_path_to_src(string_view src_file)
|
||||
fs::path get_cache_dir_path(const fs::path& src_file)
|
||||
{
|
||||
fs::path cache_dir;
|
||||
if(char* xdg_cache = getenv("XDG_CACHE_HOME"))
|
||||
if(char* XDG_CACHE = getenv("XDG_CACHE_HOME"))
|
||||
{
|
||||
cache_dir = xdg_cache;
|
||||
cache_dir = XDG_CACHE;
|
||||
cache_dir /= "cppipe";
|
||||
}
|
||||
else if(char* HOME = getenv("HOME"))
|
||||
{
|
||||
cache_dir = HOME;
|
||||
cache_dir /= ".cache/cppipe";
|
||||
}
|
||||
else
|
||||
{
|
||||
cache_dir = HOME / ".cache/cppipe";
|
||||
cache_dir = "/var/cache/cppipe";
|
||||
}
|
||||
cache_dir += fs::canonical( src_file ).parent_path();
|
||||
fs::create_directories(cache_dir);
|
||||
@@ -213,6 +236,12 @@ MappedFile mapfile_for_writing(const fs::path& file)
|
||||
res.len = lseek(fd, 0, SEEK_END);
|
||||
res.data = (char*)mmap(nullptr, res.len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
|
||||
if(res.data == (void*)-1)
|
||||
{
|
||||
cerr << "ERROR: Couldn't map " << file << " for writing\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return res;
|
||||
}
|
||||
@@ -283,8 +312,10 @@ bool preprocess_and_compare()
|
||||
// Result of preprocessing as string
|
||||
string new_pp = read_to_end(preprocessing.out);
|
||||
|
||||
if( !wait(preprocessing) ) // preprocessing failed
|
||||
exit(1);
|
||||
// TODO: decide what to do here, #! causes inevitavble non-fatal errors
|
||||
// maybe warn that preproccessing failed
|
||||
// if( !wait(preprocessing) ) // preprocessing failed
|
||||
// exit(1);
|
||||
|
||||
if( fs::exists(preprocessed_file) ) // todo: clean up if else blocks
|
||||
{
|
||||
@@ -349,11 +380,15 @@ void compile_src_file()
|
||||
compile.append_args({ CXXFLAGS });
|
||||
|
||||
|
||||
// Remap the debug source file since we compile from stdin
|
||||
string debug_remap = "-fdebug-prefix-map=<stdin>=" + src_file.string();
|
||||
if(debug)
|
||||
compile.append_args({ DEBUG_FLAGS });
|
||||
compile.append_args({ DEBUG_FLAGS, debug_remap.c_str() });
|
||||
else
|
||||
compile.append_args({ RELEASE_FLAGS });
|
||||
|
||||
for(const char* arg: additional_compiler_args)
|
||||
compile += arg;
|
||||
|
||||
if( !compile() ) // if failed to compile
|
||||
{
|
||||
@@ -365,7 +400,7 @@ void compile_src_file()
|
||||
|
||||
void print_usage()
|
||||
{
|
||||
cout << "Usage: cppipe [OPTION]... FILE [ARGUMENTS]...\n";
|
||||
cout << "Usage: cppipe [OPTION]... FILE [ARGUMENT]...\n";
|
||||
}
|
||||
|
||||
SrcType find_src_type(const string_view p)
|
||||
|
||||
+16
-16
@@ -25,7 +25,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
string out1 = $(ll + "src" | grep + "inl" | grep + "child");
|
||||
if(out1.find("childProcess.inl") != string::npos)
|
||||
cout << "OK 0/12" << endl;
|
||||
cout << "OK 0/13" << endl;
|
||||
|
||||
string out2 = $(echo + "abc" + "def");
|
||||
// "abc def" = 7 chars, trailing newlines are stripped by $()
|
||||
@@ -35,8 +35,8 @@ int main(int argc, char* argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Cmd success("echo", "OK 1/12");
|
||||
Cmd fail("mkdir", ".");
|
||||
Cmd success("echo", "OK 1/13");
|
||||
Cmd fail("false");
|
||||
Cmd unexpected("echo", "FAILURE");
|
||||
success &&
|
||||
fail &&
|
||||
@@ -47,34 +47,34 @@ int main(int argc, char* argv[])
|
||||
// unexpected &&
|
||||
// unexpected;
|
||||
|
||||
Cmd write_file("echo", "Existing ", " ", "file. OK 2/12");
|
||||
Cmd write_file("echo", "Existing ", " ", "file. OK 2/13");
|
||||
|
||||
write_file > "file.txt";
|
||||
grep + "Existing" < "file.txt";
|
||||
|
||||
echo + "Appended to file OK 3/12" >> "file.txt";
|
||||
echo + "Appended to file OK 3/13" >> "file.txt";
|
||||
grep + "Appended" < "file.txt" &&
|
||||
rm + "file.txt" &&
|
||||
fail ||
|
||||
Cmd("echo", "OK 4/12");
|
||||
Cmd("echo", "OK 4/13");
|
||||
|
||||
echo + "OK 5/12" &&
|
||||
echo + "OK 6/12",
|
||||
Cmd("echo", "OK 7/12");
|
||||
echo + "OK 5/13" &&
|
||||
echo + "OK 6/13",
|
||||
Cmd("echo", "OK 7/13");
|
||||
|
||||
echo + "OK 8/12" &
|
||||
echo + "OK 9/12" &&
|
||||
echo + "OK 10/12";
|
||||
echo + "OK 8/13" &
|
||||
echo + "OK 9/13" &&
|
||||
echo + "OK 10/13";
|
||||
|
||||
// wait for all detached
|
||||
while(wait(nullptr) != -1);
|
||||
|
||||
Cmd run_OK = echo;
|
||||
run_OK.append_args({ "OK 11/12" });
|
||||
run_OK.append_args({ "OK 11/13" });
|
||||
run( run_OK );
|
||||
|
||||
exec( echo + "OK 12/12" );
|
||||
run({ "echo", "OK 12/13" });
|
||||
|
||||
// todo
|
||||
// exec( echo + $(echo + "OK 11/12") );
|
||||
// The temporaty string is desroyed after the statement
|
||||
exec( echo + $(echo + "OK 13/13").c_str() );
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
many points in name - rc.local.start
|
||||
example #!/usr/bin/cppipe
|
||||
description - advantages over manual compile
|
||||
man
|
||||
tips (sigaction SIGCHILD, SIG_IGN, SIG_DFL)
|
||||
tips (sigaction SIGCHILD, SIG_IGN, SIG_DFL) condituonal main
|
||||
- redirected processes block if their output is not read
|
||||
make sure file descriptors are closed when no longer used
|
||||
cppipe compile options from tft
|
||||
|
||||
Reference in New Issue
Block a user