aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-09-23 12:22:37 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-06 07:39:33 +0200
commit5006226e945fc645e6d9b21252c9eee53cc191cc (patch)
tree94371016233562351d70fb3b9ff312c6dacd9bb4
parent8fdc481d78a0426f6dbf235e872c3798ec57251e (diff)
Fix various things, add generated zig header files to global include
Fix compile_commands.json missing build steps. Fix c includes -> zig includes flags. Fix crash when running sibs new/init without defining lang. Add generated zig header files to global include so they can be used from c/c++. Add zig and zig/c (using zig and c in the same project) examples.
-rw-r--r--.gitignore3
-rw-r--r--.vscode/c_cpp_properties.json7
-rw-r--r--.vscode/settings.json35
-rw-r--r--backend/ninja/Ninja.cpp144
-rwxr-xr-xcmake/build_debug.sh10
m---------depends/libninja0
-rw-r--r--examples/hello_world_c_zig/.gitignore (renamed from examples/hello_world/.gitignore)0
-rw-r--r--examples/hello_world_c_zig/project.conf8
-rw-r--r--examples/hello_world_c_zig/src/foo.zig8
-rw-r--r--examples/hello_world_c_zig/src/main.c14
-rw-r--r--examples/hello_world_c_zig/tests/main.c7
-rw-r--r--examples/hello_world_cpp/.gitignore5
-rw-r--r--examples/hello_world_cpp/project.conf (renamed from examples/hello_world/project.conf)0
-rw-r--r--examples/hello_world_cpp/src/main.cpp (renamed from examples/hello_world/src/main.cpp)0
-rw-r--r--examples/hello_world_cpp/tests/main.cpp (renamed from examples/hello_world/tests/main.cpp)0
-rw-r--r--examples/hello_world_zig/.gitignore5
-rw-r--r--examples/hello_world_zig/project.conf5
-rw-r--r--examples/hello_world_zig/src/main.zig6
-rw-r--r--include/FileUtil.hpp1
-rw-r--r--src/FileUtil.cpp30
-rw-r--r--src/main.cpp9
21 files changed, 216 insertions, 81 deletions
diff --git a/.gitignore b/.gitignore
index e2f4b7a..b086a97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,7 @@ build/
cmake/build/
cmake-build-debug/
.vs/
+.vscode/
compile_commands.json
+tests/sibs-build/
+tests/compile_commands.json
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 7748b8f..6ffabe5 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -6,12 +6,11 @@
"${workspaceFolder}/**"
],
"defines": [],
- "compilerPath": "/usr/bin/gcc",
+ "compilerPath": "/opt/cuda/bin/gcc",
"cStandard": "c11",
- "cppStandard": "c++14",
+ "cppStandard": "c++17",
"intelliSenseMode": "clang-x64",
- "compileCommands": "${workspaceFolder}/compile_commands.json",
- "configurationProvider": "vector-of-bool.cmake-tools"
+ "compileCommands": "${workspaceFolder}/compile_commands.json"
}
],
"version": 4
diff --git a/.vscode/settings.json b/.vscode/settings.json
index a06c734..57115ea 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,5 +1,19 @@
{
"files.associations": {
+ "bitset": "cpp",
+ "vector": "cpp",
+ "optional": "cpp",
+ "string_view": "cpp",
+ "system_error": "cpp",
+ "thread": "cpp",
+ "typeindex": "cpp",
+ "variant": "cpp",
+ "array": "cpp",
+ "initializer_list": "cpp",
+ "utility": "cpp",
+ "hash_map": "cpp",
+ "valarray": "cpp",
+ "*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
@@ -11,11 +25,8 @@
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
- "array": "cpp",
"atomic": "cpp",
"strstream": "cpp",
- "*.tcc": "cpp",
- "bitset": "cpp",
"chrono": "cpp",
"cinttypes": "cpp",
"codecvt": "cpp",
@@ -25,11 +36,10 @@
"deque": "cpp",
"list": "cpp",
"unordered_map": "cpp",
- "vector": "cpp",
+ "unordered_set": "cpp",
"exception": "cpp",
"fstream": "cpp",
"functional": "cpp",
- "initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
@@ -39,26 +49,15 @@
"mutex": "cpp",
"new": "cpp",
"numeric": "cpp",
- "optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
- "string_view": "cpp",
- "system_error": "cpp",
- "thread": "cpp",
"type_traits": "cpp",
"tuple": "cpp",
- "typeindex": "cpp",
"typeinfo": "cpp",
- "utility": "cpp",
- "variant": "cpp",
"__config": "cpp",
- "__nullptr": "cpp",
- "hash_map": "cpp",
- "valarray": "cpp",
- "unordered_set": "cpp"
- },
- "C_Cpp.configurationWarnings": "Disabled"
+ "__nullptr": "cpp"
+ }
} \ No newline at end of file
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index e71b22a..2c76fd4 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -219,20 +219,14 @@ namespace backend
{
string filePathStr = filepath ? filepath : "";
if(filepath && !containsSourceFile(filePathStr))
- {
sourceFiles.push_back({ language, filePathStr });
- //printf("Adding source file: %s\n", filepath);
- }
}
void Ninja::addTestSourceDir(const char *dir)
{
string dirStr = dir ? dir : "";
if(dir && !containsTestSourceDir(dirStr))
- {
testSourceDirs.emplace_back(dirStr);
- //printf("Using test source directory: %s\n", dir);
- }
}
void Ninja::addDependency(const std::string &binaryFile)
@@ -440,26 +434,7 @@ namespace backend
return result;
}
- static string convertCIncludeSyntaxToZigInclude(Compiler compiler, const string &cIncludes)
- {
- switch (compiler)
- {
- case Compiler::GCC:
- {
- return replaceAll(cIncludes, "-I", "-isystem ");
- }
- case Compiler::MSVC:
- {
- return replaceAll(cIncludes, "/I", "-isystem ");
- }
- default:
- assert(false);
- break;
- }
- return cIncludes;
- }
-
- static vector<ninja::NinjaArg> extractIncludesFromCFlag(Compiler compiler, const ninja::NinjaArg &cflag)
+ static vector<ninja::NinjaArg> extractIncludesFromCFlag(Compiler compiler, const string &cflag)
{
vector<ninja::NinjaArg> result;
string includeStartStr;
@@ -485,42 +460,52 @@ namespace backend
while(index != string::npos)
{
char endChar = ' ';
- size_t includeStartIndex = cflag.arg.find(includeStartStr, index);
+ size_t includeStartIndex = cflag.find(includeStartStr, index);
if(includeStartIndex == string::npos)
break;
else if(includeStartIndex > 0)
{
- if(cflag.arg[includeStartIndex - 1] == '"' || cflag.arg[includeStartIndex - 1] == '\'')
- endChar = cflag.arg[includeStartIndex - 1];
+ if(cflag[includeStartIndex - 1] == '"' || cflag[includeStartIndex - 1] == '\'')
+ endChar = cflag[includeStartIndex - 1];
}
includeStartIndex += includeStartStr.length();
- size_t includeEndIndex = cflag.arg.find(endChar, includeStartIndex);
+ size_t includeEndIndex = cflag.find(endChar, includeStartIndex);
index = includeEndIndex;
if(includeEndIndex == string::npos)
- includeEndIndex = cflag.arg.length();
+ includeEndIndex = cflag.length();
- result.push_back(ninja::NinjaArg::createRaw(cflag.arg.substr(includeStartIndex, includeEndIndex - includeStartIndex)));
+ result.push_back(ninja::NinjaArg::createRaw(cflag.substr(includeStartIndex, includeEndIndex - includeStartIndex)));
}
return result;
}
- static vector<ninja::NinjaArg> extractIncludesFromCFlags(Compiler compiler, const vector<ninja::NinjaArg> &cflags)
+ static vector<ninja::NinjaArg> extractIncludesFromCFlags(Compiler compiler, const vector<ninja::NinjaArg> &cflags)
{
vector<ninja::NinjaArg> result;
for(const ninja::NinjaArg &cflag : cflags)
{
- vector<ninja::NinjaArg> subCFlags = extractIncludesFromCFlag(compiler, cflag);
+ vector<ninja::NinjaArg> subCFlags = extractIncludesFromCFlag(compiler, cflag.arg);
result.insert(result.end(), subCFlags.begin(), subCFlags.end());
}
return result;
}
+ static string convertCIncludeSyntaxToZigInclude(Compiler compiler, const string &cIncludes)
+ {
+ vector<ninja::NinjaArg> result = extractIncludesFromCFlag(compiler, cIncludes);
+ string resultStr;
+ for(ninja::NinjaArg &include : result)
+ {
+ resultStr += "-isystem \"" + include.arg + "\"";
+ }
+ return resultStr;
+ }
+
static vector<ninja::NinjaArg> convertCFlagsIncludesToZigIncludes(Compiler compiler, const vector<ninja::NinjaArg> &cflags)
{
- vector<ninja::NinjaArg> result;
- result = extractIncludesFromCFlags(compiler, cflags);
+ vector<ninja::NinjaArg> result = extractIncludesFromCFlags(compiler, cflags);
for(ninja::NinjaArg &include : result)
{
include.arg = "-isystem \"" + include.arg + "\"";
@@ -596,14 +581,34 @@ namespace backend
return result;
}
- Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback)
+ static int getFilenameLength(const string &filepath)
{
- if (!sourceFiles.empty())
+ for(int i = filepath.size(); i >= 0; --i)
{
- Result<bool> createBuildDirResult = createDirectoryRecursive(savePath);
- if (createBuildDirResult.isErr())
- return createBuildDirResult;
+ char c = filepath[i];
+ if(c == '/' || c == '\\')
+ return filepath.size() - i;
}
+ return filepath.size();
+ }
+
+ Result<bool> Ninja::build(const SibsConfig &config, const _tinydir_char_t *savePath, LinkerFlagCallbackFunc staticLinkerFlagCallbackFunc, LinkerFlagCallbackFunc dynamicLinkerFlagCallback, GlobalIncludeDirCallbackFunc globalIncludeDirCallback)
+ {
+ Result<bool> createBuildDirResult = createDirectoryRecursive(savePath);
+ if (!createBuildDirResult)
+ return createBuildDirResult;
+
+ FileString generatedHeadersDir = config.getProjectPath() + TINYDIR_STRING("/sibs-build/generated-headers");
+ Result<bool> createGeneratedHeadersDirResult = createDirectoryRecursive(generatedHeadersDir.c_str());
+ if (!createGeneratedHeadersDirResult)
+ return createGeneratedHeadersDirResult;
+
+ FileString generatedZigHeadersDir = generatedHeadersDir + TINYDIR_STRING("/zig");
+ Result<bool> createGeneratedZigHeadersDirResult = createDirectory(generatedZigHeadersDir.c_str());
+ if (!createGeneratedZigHeadersDirResult)
+ return createGeneratedZigHeadersDirResult;
+
+ string generatedZigHeaderDirUtf8 = toUtf8(generatedZigHeadersDir);
LibraryType libraryType = getNinjaLibraryType(config.getPackageType());
@@ -701,6 +706,7 @@ namespace backend
}
globalIncDir += dependencyExportIncludeDirs;
+ globalIncDir += TINYDIR_STRING(" ") + getIncludeOptionFlag(config.getCompiler(), toUtf8(generatedHeadersDir));
ninjaBuildFile.defineGlobalVariable("globalIncDir", globalIncDir);
// TODO: Find a better way to convert includes, this could be slow...
ninjaBuildFile.defineGlobalVariable("globalIncDirZig", convertCIncludeSyntaxToZigInclude(config.getCompiler(), globalIncDir));
@@ -881,8 +887,10 @@ namespace backend
// TODO: Convert sibs defines to const variables in a zig file that other zig files can include (like a config file).
// TODO: Remove --library c if project does not depend on c libraries or project only has .zig files
+
+ ninja::NinjaVariable zigHeaderFile("headerFile");
vector<ninja::NinjaArg> zigTestArgs = {
- ninja::NinjaArg::createRaw("zig test $in --output $out -isystem ../../ --color on --library c $globalIncDirZig")
+ ninja::NinjaArg::createRaw("zig test $in --output $out --output-h $headerFile -isystem ../../ --color on --library c $globalIncDirZig")
};
// TODO: Find a way to do this more efficiently
@@ -891,6 +899,7 @@ namespace backend
ninja::NinjaArg::createRaw("zig build-obj"),
ninja::NinjaArg::createRaw("$in"),
ninja::NinjaArg::createRaw("--output $out"),
+ ninja::NinjaArg::createRaw("--output-h $headerFile"),
ninja::NinjaArg::createRaw("-isystem ../../"),
ninja::NinjaArg::createRaw("--color on"),
ninja::NinjaArg::createRaw("--library c"), // TODO: Remove this if project does not depend on c libraries or project only has .zig files
@@ -934,6 +943,38 @@ namespace backend
vector<string> objectNames;
objectNames.reserve(sourceFiles.size());
+ vector<ninja::NinjaBuild*> zigBuilds;
+ // TODO(Urgent): Instead of adding zig builds as dependencies for all c/c++ builds, generate two ninja files; one for zig and one for c/c++.
+ // Then build run zig ninja file first and then c/c++ ninja file.
+ // That would be more efficient as you dont need to add every single zig build as dependency for all c/c++ builds...
+ for(const sibs::SourceFile &sourceFile : sourceFiles)
+ {
+ if(sourceFile.language == sibs::Language::ZIG)
+ {
+ // TODO: Remove this and use NinjaBuilds to get object names
+ string objectName = config.getPackageName() + "@exe/" + sourceFile.filepath;
+ objectName += getObjectFileExtension(config.getCompiler());
+ objectNames.emplace_back(objectName);
+
+ // TODO: Optimize this by checking if directory has already been created with a hash map
+ int filenameLength = getFilenameLength(sourceFile.filepath);
+ string zigSourceDirRelative = sourceFile.filepath.substr(0, sourceFile.filepath.size() - filenameLength);
+ FileString zigHeaderFileDir = toFileString(generatedZigHeaderDirUtf8 + '/' + zigSourceDirRelative);
+ Result<bool> createZigHeaderFileDirResult = createDirectoryRecursive(zigHeaderFileDir.c_str());
+ if(!createZigHeaderFileDirResult)
+ return createZigHeaderFileDirResult;
+
+ string headerName = sourceFile.filepath.substr(sourceFile.filepath.size() - filenameLength, filenameLength - 4) + ".h";
+ ninja::NinjaArgValue zigHeaderFileValue = { zigHeaderFile, '"' + toUtf8(zigHeaderFileDir) + '/' + headerName + '"' };
+ ninja::NinjaBuild *ninjaBuild = nullptr;
+ if(zigTest)
+ ninjaBuild = testZigRule->build("../../" + sourceFile.filepath, objectName, { zigHeaderFileValue });
+ else
+ ninjaBuild = compileZigRule->build("../../" + sourceFile.filepath, objectName, { zigHeaderFileValue });
+ zigBuilds.push_back(ninjaBuild);
+ }
+ }
+
for(const sibs::SourceFile &sourceFile : sourceFiles)
{
string objectName;
@@ -943,7 +984,7 @@ namespace backend
{
objectName += config.getPackageName() + "@exe/" + sourceFile.filepath;
objectName += getObjectFileExtension(config.getCompiler());
- ninjaBuildFile.build(compileCRule, "../../" + sourceFile.filepath, objectName, {});
+ compileCRule->build("../../" + sourceFile.filepath, objectName, {}, zigBuilds);
usesCFiles = true;
break;
}
@@ -951,18 +992,13 @@ namespace backend
{
objectName += config.getPackageName() + "@exe/" + sourceFile.filepath;
objectName += getObjectFileExtension(config.getCompiler());
- ninjaBuildFile.build(compileCppRule, "../../" + sourceFile.filepath, objectName, {});
+ compileCppRule->build("../../" + sourceFile.filepath, objectName, {}, zigBuilds);
usesCppFiles = true;
break;
}
case sibs::Language::ZIG:
{
- objectName += "zig-cache/" + sourceFile.filepath;
- objectName += getObjectFileExtension(config.getCompiler());
- if(zigTest)
- ninjaBuildFile.build(testZigRule, "../../" + sourceFile.filepath, objectName, {});
- else
- ninjaBuildFile.build(compileZigRule, "../../" + sourceFile.filepath, objectName, {});
+ // Already built above
break;
}
default:
@@ -1041,7 +1077,7 @@ namespace backend
buildExeArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags));
ninja::NinjaRule *buildExeRule = ninjaBuildFile.createRule("build_exec", buildExeArgs);
- ninjaBuildFile.build(buildExeRule, join(objectNames, " "), config.getPackageName(), {});
+ buildExeRule->build(join(objectNames, " "), config.getPackageName(), {});
projectGeneratedBinary += config.getPackageName();
#if OS_FAMILY == OS_FAMILY_WINDOWS
@@ -1079,7 +1115,7 @@ namespace backend
}
ninja::NinjaRule *buildStaticRule = ninjaBuildFile.createRule("build_static", buildStaticArgs);
- ninjaBuildFile.build(buildStaticRule, join(objectNames, " "), generatedFile, {});
+ buildStaticRule->build(join(objectNames, " "), generatedFile, {});
projectGeneratedBinary += generatedFile;
projectGeneratedBinary += "\"";
@@ -1149,7 +1185,7 @@ namespace backend
buildDynamicArgs.push_back(ninja::NinjaArg::createRaw(allLinkerFlags));
ninja::NinjaRule *buildDynamicRule = ninjaBuildFile.createRule("build_dynamic", buildDynamicArgs);
- ninjaBuildFile.build(buildDynamicRule, join(objectNames, " "), generatedFile, {});
+ buildDynamicRule->build(join(objectNames, " "), generatedFile, {});
projectGeneratedBinary += generatedFile;
projectGeneratedBinary += "\"";
@@ -1348,7 +1384,7 @@ namespace backend
{
FileString command = TINYDIR_STRING("ninja -C \"");
command += buildFilePath;
- command += TINYDIR_STRING("\" -t compdb c_COMPILER cpp_COMPILER BUILD_EXEC BUILD_STATIC BUILD_DYNAMIC > \"");
+ command += TINYDIR_STRING("\" -t compdb compile_c compile_cpp compile_zig > \"");
command += saveDir;
command += TINYDIR_STRING("/compile_commands.json\"");
Result<ExecResult> execResult = exec(command.c_str(), false);
diff --git a/cmake/build_debug.sh b/cmake/build_debug.sh
new file mode 100755
index 0000000..45dceeb
--- /dev/null
+++ b/cmake/build_debug.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/env bash
+
+set -e
+
+scriptpath="$(dirname "$0")"
+mkdir -p "$scriptpath/build/debug"
+cd "$scriptpath/build/debug"
+cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug ../../../
+ninja
+echo "Debug build success"
diff --git a/depends/libninja b/depends/libninja
-Subproject efd1bdf5576ddcff21fecc0ff5efa4d53aa8d08
+Subproject 2698cbc14f8a2a108a3252f03e053cb47b8b510
diff --git a/examples/hello_world/.gitignore b/examples/hello_world_c_zig/.gitignore
index 636c6b9..636c6b9 100644
--- a/examples/hello_world/.gitignore
+++ b/examples/hello_world_c_zig/.gitignore
diff --git a/examples/hello_world_c_zig/project.conf b/examples/hello_world_c_zig/project.conf
new file mode 100644
index 0000000..fa006cd
--- /dev/null
+++ b/examples/hello_world_c_zig/project.conf
@@ -0,0 +1,8 @@
+[package]
+name = "hello_world_c_zig"
+type = "executable"
+version = "0.1.0"
+platforms = ["linux64"]
+tests = "tests"
+
+[dependencies]
diff --git a/examples/hello_world_c_zig/src/foo.zig b/examples/hello_world_c_zig/src/foo.zig
new file mode 100644
index 0000000..464eadd
--- /dev/null
+++ b/examples/hello_world_c_zig/src/foo.zig
@@ -0,0 +1,8 @@
+const warn = @import("std").debug.warn;
+
+extern fn baz() void;
+
+export fn foo() void {
+ warn("zig called from c!\n");
+ baz();
+}
diff --git a/examples/hello_world_c_zig/src/main.c b/examples/hello_world_c_zig/src/main.c
new file mode 100644
index 0000000..aeaeae4
--- /dev/null
+++ b/examples/hello_world_c_zig/src/main.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <zig/src/foo.h>
+
+void baz()
+{
+ printf("c called from zig!\n");
+}
+
+int main(int argc, char **argv)
+{
+ printf("inside c\n");
+ foo();
+ return 0;
+}
diff --git a/examples/hello_world_c_zig/tests/main.c b/examples/hello_world_c_zig/tests/main.c
new file mode 100644
index 0000000..9ad80a6
--- /dev/null
+++ b/examples/hello_world_c_zig/tests/main.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ printf("hello, world!\n");
+ return 0;
+}
diff --git a/examples/hello_world_cpp/.gitignore b/examples/hello_world_cpp/.gitignore
new file mode 100644
index 0000000..636c6b9
--- /dev/null
+++ b/examples/hello_world_cpp/.gitignore
@@ -0,0 +1,5 @@
+# Compiled sibs files
+sibs-build/
+compile_commands.json
+tests/sibs-build/
+tests/compile_commands.json
diff --git a/examples/hello_world/project.conf b/examples/hello_world_cpp/project.conf
index 4c05ce5..4c05ce5 100644
--- a/examples/hello_world/project.conf
+++ b/examples/hello_world_cpp/project.conf
diff --git a/examples/hello_world/src/main.cpp b/examples/hello_world_cpp/src/main.cpp
index 28bab08..28bab08 100644
--- a/examples/hello_world/src/main.cpp
+++ b/examples/hello_world_cpp/src/main.cpp
diff --git a/examples/hello_world/tests/main.cpp b/examples/hello_world_cpp/tests/main.cpp
index 28bab08..28bab08 100644
--- a/examples/hello_world/tests/main.cpp
+++ b/examples/hello_world_cpp/tests/main.cpp
diff --git a/examples/hello_world_zig/.gitignore b/examples/hello_world_zig/.gitignore
new file mode 100644
index 0000000..636c6b9
--- /dev/null
+++ b/examples/hello_world_zig/.gitignore
@@ -0,0 +1,5 @@
+# Compiled sibs files
+sibs-build/
+compile_commands.json
+tests/sibs-build/
+tests/compile_commands.json
diff --git a/examples/hello_world_zig/project.conf b/examples/hello_world_zig/project.conf
new file mode 100644
index 0000000..6ad2e1b
--- /dev/null
+++ b/examples/hello_world_zig/project.conf
@@ -0,0 +1,5 @@
+[package]
+name = "hello_world_zig"
+type = "executable"
+version = "0.1.0"
+platforms = ["any"]
diff --git a/examples/hello_world_zig/src/main.zig b/examples/hello_world_zig/src/main.zig
new file mode 100644
index 0000000..c74a3de
--- /dev/null
+++ b/examples/hello_world_zig/src/main.zig
@@ -0,0 +1,6 @@
+const warn = @import("std").debug.warn;
+
+pub fn main() void
+{
+ warn("Hello, world!\n");
+}
diff --git a/include/FileUtil.hpp b/include/FileUtil.hpp
index b808573..aa2b82f 100644
--- a/include/FileUtil.hpp
+++ b/include/FileUtil.hpp
@@ -53,6 +53,7 @@ namespace sibs
Result<bool> fileOverwrite(const _tinydir_char_t *filepath, StringView data);
Result<FileString> getHomeDir();
Result<FileString> getCwd();
+ Result<bool> createDirectory(const _tinydir_char_t *path);
// Note: Will not delete created directories if this operation fails for some reason
Result<bool> createDirectoryRecursive(const _tinydir_char_t *path);
Result<FileString> getRealPath(const _tinydir_char_t *path);
diff --git a/src/FileUtil.cpp b/src/FileUtil.cpp
index aca2778..53430c4 100644
--- a/src/FileUtil.cpp
+++ b/src/FileUtil.cpp
@@ -288,6 +288,31 @@ namespace sibs
return Result<FileString>::Err(strerror(errno));
}
+ Result<bool> createDirectory(const _tinydir_char_t *path)
+ {
+ size_t pathLength = strlen(path);
+ if(pathLength > _TINYDIR_PATH_MAX - 1)
+ {
+ string errMsg = "Directory path too long: ";
+ errMsg += string(path, pathLength);
+ return Result<bool>::Err(errMsg, ENAMETOOLONG);
+ }
+
+ if(mkdir(path, S_IRWXU) != 0)
+ {
+ int error = errno;
+ if(error != EEXIST)
+ {
+ string errMsg = "Failed to create directory: ";
+ errMsg += toUtf8(path);
+ errMsg += "; reason: ";
+ errMsg += strerror(error);
+ return Result<bool>::Err(errMsg, error);
+ }
+ }
+ return Result<bool>::Ok(true);
+ }
+
Result<bool> createDirectoryRecursive(const _tinydir_char_t *path)
{
char pathBuffer[_TINYDIR_PATH_MAX];
@@ -303,7 +328,8 @@ namespace sibs
char *p = pathBuffer;
for(size_t i = 0; i < pathLength; ++i)
{
- if(i > 0 && *p == '/')
+ char c = *p;
+ if(i > 0 && (c == '/' || c == '\\'))
{
*p = '\0';
if(mkdir(pathBuffer, S_IRWXU) != 0)
@@ -318,7 +344,7 @@ namespace sibs
return Result<bool>::Err(errMsg, error);
}
}
- *p = '/';
+ *p = c;
}
++p;
}
diff --git a/src/main.cpp b/src/main.cpp
index b232d93..0d29a75 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -701,6 +701,9 @@ int initProject(int argc, const _tinydir_char_t **argv)
ferr << "Error: Project type not defined, expected to be either --exec, --static or --dynamic" << endl;
usageInit();
}
+
+ if(!lang)
+ lang = TINYDIR_STRING("c++");
string projectTypeConf;
if(_tinydir_strcmp(projectType, TINYDIR_STRING("--exec")) == 0)
@@ -714,9 +717,6 @@ int initProject(int argc, const _tinydir_char_t **argv)
ferr << "Expected project type to be either --exec, --static or --dynamic; was: " << projectType << endl << endl;
usageInit();
}
-
- if(!lang)
- lang = TINYDIR_STRING("c++");
// TODO: If projectPath is not defined and working directory does not contain project.conf, then search every parent directory until one is found
if(projectPath.empty())
@@ -920,6 +920,9 @@ int newProject(int argc, const _tinydir_char_t **argv)
ferr << "Error: Project type not defined, expected to be either --exec, --static or --dynamic" << endl;
usageNew();
}
+
+ if(!lang)
+ lang = TINYDIR_STRING("c++");
string projectTypeConf;
if(_tinydir_strcmp(projectType, TINYDIR_STRING("--exec")) == 0)