aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/ninja/Ninja.cpp17
-rw-r--r--src/Exec.cpp2
-rw-r--r--src/main.cpp107
3 files changed, 96 insertions, 30 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index 8b815cb..fad1d35 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -12,6 +12,7 @@ using namespace std;
using namespace sibs;
#if OS_FAMILY == OS_FAMILY_POSIX
+#include <unistd.h>
#define nprintf printf
#else
#define nprintf wprintf
@@ -1889,9 +1890,19 @@ namespace backend
Result<bool> Ninja::compile(const _tinydir_char_t *buildFilePath)
{
#if OS_TYPE == OS_TYPE_LINUX
- FileString command = TINYDIR_STRING("script -eqc 'ninja -C \"");
- command += buildFilePath;
- command += TINYDIR_STRING("\"' /dev/null");
+ FileString command;
+ if(isatty(STDOUT_FILENO) == 1)
+ {
+ command = TINYDIR_STRING("script -eqc 'ninja -C \"");
+ command += buildFilePath;
+ command += TINYDIR_STRING("\"' /dev/null");
+ }
+ else
+ {
+ command = TINYDIR_STRING("ninja -C \"");
+ command += buildFilePath;
+ command += TINYDIR_STRING("\"");
+ }
#else
FileString command = TINYDIR_STRING("ninja -C \"");
command += buildFilePath;
diff --git a/src/Exec.cpp b/src/Exec.cpp
index cc82897..169858f 100644
--- a/src/Exec.cpp
+++ b/src/Exec.cpp
@@ -7,7 +7,7 @@
using namespace std;
-const int BUFSIZE = 1024;
+const int BUFSIZE = 4096;
// TODO: Redirect stderr to
namespace sibs
diff --git a/src/main.cpp b/src/main.cpp
index cc1f4a5..8282889 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -118,6 +118,7 @@ static void usage()
printf("Simple Build System for Native Languages\n\n");
printf("Commands:\n");
printf(" build Build a project that contains a project.conf file\n");
+ printf(" run Build and run a project that contains a project.conf file\n");
printf(" new Create a new project\n");
printf(" init Initialize project in an existing directory\n");
printf(" test Build and run tests for a sibs project\n");
@@ -127,22 +128,24 @@ static void usage()
exit(1);
}
-static void usageBuild()
+static void usageBuild(bool run)
{
- printf("Usage: sibs build [project_path] [--debug|--release] [--sanitize=(address|undefined|leak|thread|none)] [--platform <platform>]\n\n");
- printf("Build a sibs project\n\n");
+ printf("Usage: sibs %s [project_path] [--debug|--release] [--sanitize=(address|undefined|leak|thread|none)] [--platform <platform>]\n\n", run ? "run" : "build");
+ printf("%s a sibs project\n\n", run ? "Build and run" : "Build");
printf("Options:\n");
printf(" project_path The directory containing a project.conf file - Optional (default: current directory)\n");
printf(" --debug|--release Optimization level to build project and dependencies with (if not a system package) - Optional (default: --debug)\n");
printf(" --sanitize Add runtime address/undefined behavior sanitization. Program can be up to 3 times slower and use 10 times as much RAM. Ignored if compiler doesn't support sanitization - Optional (default: none)\n");
printf(" --platform The platform to build for - Optional (default: the running platform)\n");
printf("Examples:\n");
- printf(" sibs build\n");
- printf(" sibs build dirA/dirB\n");
- printf(" sibs build --release\n");
- printf(" sibs build dirA --release\n");
- printf(" sibs build --sanitize=address\n");
- printf(" sibs build --release --platform win64\n");
+ printf(" sibs %s\n", run ? "run" : "build");
+ if(run)
+ printf(" sibs run --args hello world\n");
+ printf(" sibs %s dirA/dirB\n", run ? "run" : "build");
+ printf(" sibs %s --release\n", run ? "run" : "build");
+ printf(" sibs %s dirA --release\n", run ? "run" : "build");
+ printf(" sibs %s --sanitize=address\n", run ? "run" : "build");
+ printf(" sibs %s --release --platform win64\n", run ? "run" : "build");
exit(1);
}
@@ -359,7 +362,7 @@ static void appendBuildToolToPathEnv()
#endif
}
-static int buildProject(const FileString &projectPath, const FileString &projectConfFilePath, SibsConfig &sibsConfig)
+static int buildProject(const FileString &projectPath, const FileString &projectConfFilePath, SibsConfig &sibsConfig, bool run, FileString run_args)
{
FileString buildPath;
readSibsConfig(projectPath, projectConfFilePath, sibsConfig, buildPath);
@@ -375,7 +378,7 @@ static int buildProject(const FileString &projectPath, const FileString &project
sibsConfig.setPackageType(PackageType::DYNAMIC);
}
- auto startTime = high_resolution_clock::now();
+ auto startTime = steady_clock::now();
if(sibsConfig.shouldUseCmake())
{
auto dummyCallback = [](const string&){};
@@ -444,12 +447,53 @@ static int buildProject(const FileString &projectPath, const FileString &project
exit(7);
}
}
- auto elapsedTime = duration_cast<duration<double>>(high_resolution_clock::now() - startTime);
- printf("Finished in %fs\n", elapsedTime.count());
+ auto elapsedTime = duration_cast<duration<double>>(steady_clock::now() - startTime);
+ printf("Finished building in %fs\n", elapsedTime.count());
+
+ if(run) {
+ FileString executableName = toFileString(sibsConfig.getPackageName());
+ if(isSamePlatformFamily(sibsConfig.platform, PLATFORM_WIN))
+ executableName += TINYDIR_STRING(".exe");
+ auto exec_result = exec(buildPath + TINYDIR_STRING("/") + executableName + TINYDIR_STRING(" ") + run_args, true);
+ if(!exec_result) {
+ ferr << "Failed to execute" << (buildPath + TINYDIR_STRING("/") + executableName) << ", error: " << toFileString(exec_result.getErrMsg()) << endl;
+ return 1;
+ }
+ return exec_result.getErrorCode();
+ }
return 0;
}
+#if OS_FAMILY == OS_FAMILY_WINDOWS
+#define NATIVE_CHAR_PREFIX L
+#else
+#define NATIVE_CHAR_PREFIX
+#endif
+
+static FileString replace_all(const _tinydir_char_t *str) {
+ FileString result = TINYDIR_STRING("'");
+ while(*str != NATIVE_CHAR_PREFIX'\0') {
+ if(*str == NATIVE_CHAR_PREFIX'\'')
+ result += TINYDIR_STRING("\\'");
+ else
+ result += *str;
+ ++str;
+ }
+ result += NATIVE_CHAR_PREFIX'\'';
+ return result;
+}
+
+static FileString escape_args(const std::vector<const _tinydir_char_t*> &args) {
+ FileString result;
+ for(const _tinydir_char_t *arg : args) {
+ if(!result.empty())
+ result += NATIVE_CHAR_PREFIX' ';
+ result += replace_all(arg);
+ }
+ return result;
+}
+
static Sanitize sanitize_string_to_type(const _tinydir_char_t *str) {
if(strcmp(str, TINYDIR_STRING("address")) == 0)
return Sanitize::ADDRESS;
@@ -465,12 +509,13 @@ static Sanitize sanitize_string_to_type(const _tinydir_char_t *str) {
return SANITIZE_INVALID;
}
-static int buildProject(int argc, const _tinydir_char_t **argv)
+static int buildProject(int argc, const _tinydir_char_t **argv, bool run)
{
OptimizationLevel optimizationLevel = OPT_LEV_NONE;
FileString projectPath;
Sanitize sanitize = Sanitize::NONE;
FileString platformName;
+ std::vector<const _tinydir_char_t*> run_args;
for(int i = 0; i < argc; ++i)
{
@@ -480,7 +525,7 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
if(optimizationLevel != OPT_LEV_NONE)
{
ferr << "Error: Optimization level defined more than once. First defined as " << asString(optimizationLevel) << " then as debug" << endl;
- usageBuild();
+ usageBuild(run);
}
optimizationLevel = OPT_LEV_DEBUG;
}
@@ -489,7 +534,7 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
if(optimizationLevel != OPT_LEV_NONE)
{
ferr << "Error: Optimization level defined more than once. First defined as " << asString(optimizationLevel) << " then as release" << endl;
- usageBuild();
+ usageBuild(run);
}
optimizationLevel = OPT_LEV_RELEASE;
}
@@ -498,7 +543,7 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
sanitize = sanitize_string_to_type(arg + 11);
if(sanitize == SANITIZE_INVALID) {
ferr << "Error: Invalid sanitize option " << (arg + 11) << ", expected address, undefined, leak, thread or none" << endl;
- usageBuild();
+ usageBuild(run);
}
}
else if(_tinydir_strcmp(arg, TINYDIR_STRING("--platform")) == 0)
@@ -506,7 +551,7 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
if(i == argc - 1)
{
ferr << "Error: Expected platform to target after --platform" << endl;
- usageBuild();
+ usageBuild(run);
}
++i;
@@ -515,21 +560,26 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
if(!platformName.empty())
{
ferr << "Error: Platform defined twice. First as " << platformName << " then as " << arg << endl;
- usageBuild();
+ usageBuild(run);
}
platformName = arg;
}
+ else if(run && _tinydir_strcmp(arg, TINYDIR_STRING("--args")) == 0)
+ {
+ run_args.insert(run_args.end(), argv + i + 1, argv + argc);
+ break;
+ }
else if(_tinydir_strncmp(arg, TINYDIR_STRING("--"), 2) == 0)
{
ferr << "Error: Invalid argument " << arg << endl;
- usageBuild();
+ usageBuild(run);
}
else
{
if(!projectPath.empty())
{
ferr << "Error: Project path was defined more than once. First defined as " << projectPath << " then as " << arg << endl;
- usageBuild();
+ usageBuild(run);
}
projectPath = arg;
}
@@ -547,7 +597,7 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
{
ferr << "Invalid platform " << platformName << endl;
ferr << "Expected one of: " << getPlatformListFormatted() << std::endl;
- usageBuild();
+ usageBuild(run);
}
bool crossCompileLinux64ToWin64 = (SYSTEM_PLATFORM == PLATFORM_LINUX_X86_64 && platform == PLATFORM_WIN64);
@@ -595,7 +645,7 @@ static int buildProject(int argc, const _tinydir_char_t **argv)
sibsConfig.showWarnings = true;
sibsConfig.platform = platform;
sibsConfig.setSanitize(sanitize);
- return buildProject(projectPath, projectConfFilePath, sibsConfig);
+ return buildProject(projectPath, projectConfFilePath, sibsConfig, run, escape_args(run_args));
}
static int testProject(int argc, const _tinydir_char_t **argv)
@@ -740,7 +790,7 @@ static int testProject(int argc, const _tinydir_char_t **argv)
sibsConfig.zigTestFiles = move(filesToTest);
sibsConfig.zigTestAllFiles = testAllFiles;
- return buildProject(projectPath, projectConfFilePath, sibsConfig);
+ return buildProject(projectPath, projectConfFilePath, sibsConfig, false, TINYDIR_STRING(""));
}
// Returns nullptr if @charToFind is not found
@@ -1178,7 +1228,7 @@ static int packageProject(int argc, const _tinydir_char_t **argv)
sibsConfig.showWarnings = true;
sibsConfig.packaging = packagingType == PackagingType::STATIC;
sibsConfig.bundling = (packagingType == PackagingType::BUNDLE) || (packagingType == PackagingType::BUNDLE_INSTALL);
- int result = buildProject(projectPath, projectConfFilePath, sibsConfig);
+ int result = buildProject(projectPath, projectConfFilePath, sibsConfig, false, TINYDIR_STRING(""));
if(result != 0)
return result;
@@ -1438,7 +1488,12 @@ int wmain(int argc, const _tinydir_char_t **argv)
if(_tinydir_strcmp(arg, TINYDIR_STRING("build")) == 0)
{
appendBuildToolToPathEnv();
- return buildProject(subCommandArgCount, subCommandArgPtr);
+ return buildProject(subCommandArgCount, subCommandArgPtr, false);
+ }
+ else if(_tinydir_strcmp(arg, TINYDIR_STRING("run")) == 0)
+ {
+ appendBuildToolToPathEnv();
+ return buildProject(subCommandArgCount, subCommandArgPtr, true);
}
else if(_tinydir_strcmp(arg, TINYDIR_STRING("new")) == 0)
{