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