aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2018-05-24 03:23:50 +0200
committerdec05eba <dec05eba@protonmail.com>2020-07-06 07:39:32 +0200
commit25601fbac722b9af61ebaf69014e4b73517aaf94 (patch)
treea89ed3fe91e1aae153e832f1362c5765e064f533
parent2cee880ef4ba9f4369b7e464eec87c4fec55d7fc (diff)
Add sanitize build/test option, currently ignored if gcc is not used
-rw-r--r--backend/ninja/Ninja.cpp18
-rw-r--r--include/Conf.hpp14
-rw-r--r--sibs_multilib.kdev44
-rw-r--r--src/CmakeModule.cpp8
-rw-r--r--src/main.cpp56
5 files changed, 87 insertions, 13 deletions
diff --git a/backend/ninja/Ninja.cpp b/backend/ninja/Ninja.cpp
index 35922ee..c72c99f 100644
--- a/backend/ninja/Ninja.cpp
+++ b/backend/ninja/Ninja.cpp
@@ -722,12 +722,17 @@ namespace backend
switch (config.getOptimizationLevel())
{
case OPT_LEV_DEBUG:
- result += " -g3 -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS -fasynchronous-unwind-tables -fsanitize=address -fsanitize=undefined ";
+ result += " -g3 -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS -fasynchronous-unwind-tables";
break;
case OPT_LEV_RELEASE:
result += " -g0";
break;
}
+
+ if(config.getSanitize())
+ {
+ result += " -fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined";
+ }
break;
}
case Compiler::MSVC:
@@ -782,7 +787,10 @@ namespace backend
case Compiler::GCC:
{
// TODO: Add flag to disable -ldl and -lm (dlopen, dlclose, floor, max, ...)
- result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' -ldl -lm ";
+ result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed'";
+ if(config.getSanitize())
+ result += " -lasan -lubsan";
+ result += " -ldl -lm ";
break;
}
case Compiler::MSVC:
@@ -848,7 +856,10 @@ namespace backend
result += ".so: " + buildJob + " ";
result += join(objectNames, " ");
result += "\n";
- result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed' -ldl -lm ";
+ result += " LINK_ARGS = '-Wl,--no-undefined,--as-needed'";
+ if(config.getSanitize())
+ result += " -lasan -lubsan";
+ result += " -ldl -lm ";
projectGeneratedBinary += "lib" + config.getPackageName() + ".so";
break;
}
@@ -946,6 +957,7 @@ namespace backend
FileType projectConfFileType = getFileType(projectConfFilePath.c_str());
SibsTestConfig sibsTestConfig(config.getCompiler(), testSourceDirNative, config.getOptimizationLevel());
+ sibsTestConfig.setSanitize(config.getSanitize());
if(projectConfFileType == FileType::REGULAR)
{
Result<bool> result = Config::readFromFile(projectConfFilePath.c_str(), sibsTestConfig);
diff --git a/include/Conf.hpp b/include/Conf.hpp
index 6018b48..c8c22e1 100644
--- a/include/Conf.hpp
+++ b/include/Conf.hpp
@@ -213,7 +213,8 @@ namespace sibs
buildTests(_buildTests),
cVersion(CVersion::C11),
cppVersion(CPPVersion::CPP14),
- mainProject(false)
+ mainProject(false),
+ sanitize(false)
{
cmakeDirGlobal = projectPath;
cmakeDirStatic = cmakeDirGlobal;
@@ -388,6 +389,16 @@ namespace sibs
this->mainProject = mainProject;
}
+ bool getSanitize() const
+ {
+ return sanitize;
+ }
+
+ void setSanitize(bool sanitize)
+ {
+ this->sanitize = sanitize;
+ }
+
virtual bool isDefined(const std::string &name) const;
virtual bool define(const std::string &name, const std::string &value);
virtual const std::unordered_map<std::string, std::string>& getDefines() const;
@@ -440,6 +451,7 @@ namespace sibs
bool buildTests;
bool finishedProcessing;
bool mainProject;
+ bool sanitize;
};
class SibsTestConfig : public SibsConfig
diff --git a/sibs_multilib.kdev4 b/sibs_multilib.kdev4
new file mode 100644
index 0000000..298eb30
--- /dev/null
+++ b/sibs_multilib.kdev4
@@ -0,0 +1,4 @@
+[Project]
+CreatedFrom=
+Manager=KDevCustomBuildSystem
+Name=sibs_multilib
diff --git a/src/CmakeModule.cpp b/src/CmakeModule.cpp
index 15597cb..27047ba 100644
--- a/src/CmakeModule.cpp
+++ b/src/CmakeModule.cpp
@@ -121,6 +121,14 @@ namespace sibs
return createBuildDirResult;
FileString cmd = TINYDIR_STRING("cmake ");
+ if(config.getCompiler() == Compiler::GCC)
+ {
+ if(config.getSanitize())
+ {
+ cmd += TINYDIR_STRING(" \"-CMAKE_C_FLAGS=-fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined -lasan -lubsan\" "
+ "\"-CMAKE_CXX_FLAGS=-fno-omit-frame-pointer -fsanitize=address -fsanitize=undefined -lasan -lubsan\"");
+ }
+ }
switch(config.getPackageType())
{
case PackageType::EXECUTABLE:
diff --git a/src/main.cpp b/src/main.cpp
index db57648..134d2c6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -108,16 +108,18 @@ void usage()
void usageBuild()
{
- printf("Usage: sibs build [project_path] [--debug|--release]\n\n");
+ printf("Usage: sibs build [project_path] [--debug|--release] [--sanitize]\n\n");
printf("Build a sibs project\n\n");
printf("Options:\n");
- printf(" project_path\t\t The directory containing a project.conf file - Optional (default: current working directory)\n");
+ printf(" project_path\t\tThe directory containing a project.conf file - Optional (default: current working directory)\n");
printf(" --debug|--release\t\tOptimization level to build project and dependencies with (if not a system package) - Optional (default: --debug)\n");
+ printf(" --sanitize\t\tAdd runtime address/undefined behavior sanitization. Program can be up to 3 times slower and use 3 times as much RAM. Ignored if compiler doesn't support sanitization - Optional (default: disabled)\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\n");
exit(1);
}
@@ -137,10 +139,11 @@ void usageNew()
void usageTest()
{
- printf("Usage: sibs test [project_path]\n\n");
+ printf("Usage: sibs test [project_path] [--no-sanitize]\n\n");
printf("Build and run tests for a sibs project\n\n");
printf("Options:\n");
- printf(" project_path\t\t The directory containing a project.conf file - Optional (default: current working directory)\n");
+ printf(" project_path\t\tThe directory containing a project.conf file - Optional (default: current working directory)\n");
+ printf(" --no-sanitize\t\tDisable runtime address/undefined behavior - Optional\n");
printf("Examples:\n");
printf(" sibs test\n");
printf(" sibs test dirA/dirB\n");
@@ -213,6 +216,7 @@ int buildProject(const FileString &projectPath, const FileString &projectConfFil
// It's ok if `define` fails. It could fail if `main` has already been replaced by other tests somehow.
sibsConfig.define("main", "sibs_lib_ignore_main");
sibsConfig.define("wmain", "sibs_lib_ignore_wmain");
+ sibsConfig.define("WinMain", "sibs_lib_ignore_WinMain");
sibsConfig.setPackageType(PackageType::DYNAMIC);
}
@@ -279,11 +283,12 @@ int buildProject(const FileString &projectPath, const FileString &projectConfFil
int buildProject(int argc, const _tinydir_char_t **argv)
{
- if(argc > 2)
+ if(argc > 3)
usageBuild();
OptimizationLevel optimizationLevel = OPT_LEV_NONE;
FileString projectPath;
+ bool sanitize = false;
for(int i = 0; i < argc; ++i)
{
@@ -306,6 +311,15 @@ int buildProject(int argc, const _tinydir_char_t **argv)
}
optimizationLevel = OPT_LEV_RELEASE;
}
+ else if(_tinydir_strcmp(arg, TINYDIR_STRING("--sanitize")) == 0)
+ {
+ sanitize = true;
+ }
+ else if(_tinydir_strncmp(arg, TINYDIR_STRING("--"), 2) == 0)
+ {
+ ferr << "Error: Invalid argument " << arg << endl;
+ usageBuild();
+ }
else
{
if(!projectPath.empty())
@@ -349,6 +363,7 @@ int buildProject(int argc, const _tinydir_char_t **argv)
#endif
SibsConfig sibsConfig(compiler, projectPath, optimizationLevel, false);
+ sibsConfig.setSanitize(sanitize);
return buildProject(projectPath, projectConfFilePath, sibsConfig);
}
@@ -356,10 +371,32 @@ int testProject(int argc, const _tinydir_char_t **argv)
{
if(argc > 1)
usageTest();
-
+
FileString projectPath;
- if(argc == 1)
- projectPath = argv[0];
+ bool sanitize = true;
+
+ for(int i = 0; i < argc; ++i)
+ {
+ const _tinydir_char_t *arg = argv[i];
+ if(_tinydir_strcmp(arg, TINYDIR_STRING("--no-sanitize")) == 0)
+ {
+ sanitize = false;
+ }
+ else if(_tinydir_strncmp(arg, TINYDIR_STRING("--"), 2) == 0)
+ {
+ ferr << "Error: Invalid argument " << arg << endl;
+ usageTest();
+ }
+ else
+ {
+ if(!projectPath.empty())
+ {
+ ferr << "Error: Project path was defined more than once. First defined as " << projectPath << " then as " << arg << endl;
+ usageTest();
+ }
+ projectPath = arg;
+ }
+ }
// 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())
@@ -390,6 +427,7 @@ int testProject(int argc, const _tinydir_char_t **argv)
#endif
SibsConfig sibsConfig(compiler, projectPath, OPT_LEV_DEBUG, true);
+ sibsConfig.setSanitize(sanitize);
return buildProject(projectPath, projectConfFilePath, sibsConfig);
}
@@ -543,7 +581,7 @@ int wmain(int argc, const _tinydir_char_t **argv)
}
else
{
- ferr << "Expected command to be either 'build' or 'new', was: " << arg << endl << endl;
+ ferr << "Expected command to be either 'build', 'new' or 'test', was: " << arg << endl << endl;
usage();
}
}