Skip to content

Commit 3db4d7c

Browse files
committed
fixed #12465 - added command-line option --executor to specify the used executor implementation
1 parent 91f15aa commit 3db4d7c

11 files changed

+198
-13
lines changed

cli/cmdlineparser.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
374374

375375
ImportProject project;
376376

377+
bool executorAuto = true;
377378
int8_t logMissingInclude{0};
378379

379380
for (int i = 1; i < argc; i++) {
@@ -614,6 +615,36 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
614615
#endif
615616
}
616617

618+
else if (std::strncmp(argv[i], "--executor=", 11) == 0) {
619+
const std::string type = 11 + argv[i];
620+
if (type == "auto") {
621+
executorAuto = true;
622+
mSettings.executor = Settings::defaultExecutor();
623+
}
624+
else if (type == "thread") {
625+
#if defined(HAS_THREADING_MODEL_THREAD)
626+
executorAuto = false;
627+
mSettings.executor = Settings::ExecutorType::Thread;
628+
#else
629+
mLogger.printError("executor type 'thread' cannot be used as Cppcheck has not been built with a respective threading model.");
630+
return Result::Fail;
631+
#endif
632+
}
633+
else if (type == "process") {
634+
#if defined(HAS_THREADING_MODEL_FORK)
635+
executorAuto = false;
636+
mSettings.executor = Settings::ExecutorType::Process;
637+
#else
638+
mLogger.printError("executor type 'process' cannot be used as Cppcheck has not been built with a respective threading model.");
639+
return Result::Fail;
640+
#endif
641+
}
642+
else {
643+
mLogger.printError("unknown executor: '" + type + "'.");
644+
return Result::Fail;
645+
}
646+
}
647+
617648
// Filter errors
618649
else if (std::strncmp(argv[i], "--exitcode-suppressions=", 24) == 0) {
619650
// exitcode-suppressions=filename.txt
@@ -1274,6 +1305,10 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
12741305
if (!loadCppcheckCfg())
12751306
return Result::Fail;
12761307

1308+
// TODO: bail out?
1309+
if (!executorAuto && mSettings.useSingleJob())
1310+
mLogger.printMessage("'--executor' has no effect as only a single job will be used.");
1311+
12771312
// Default template format..
12781313
if (mSettings.templateFormat.empty()) {
12791314
mSettings.templateFormat = "{bold}{file}:{line}:{column}: {red}{inconclusive:{magenta}}{severity}:{inconclusive: inconclusive:}{default} {message} [{id}]{reset}\\n{code}";
@@ -1430,6 +1465,8 @@ void CmdLineParser::printHelp() const
14301465
" provided. Note that your operating system can modify\n"
14311466
" this value, e.g. '256' can become '0'.\n"
14321467
" --errorlist Print a list of all the error messages in XML format.\n"
1468+
" --executor=<type>\n"
1469+
" Specifies the executor to use. Possible values: auto, thread, processor.\n"
14331470
" --exitcode-suppressions=<file>\n"
14341471
" Used when certain messages should be displayed but\n"
14351472
" should not cause a non-zero exitcode.\n"

cli/cppcheckexecutor.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,18 +266,24 @@ int CppCheckExecutor::check_internal(const Settings& settings) const
266266
cppcheck.settings() = settings; // this is a copy
267267
auto& suppressions = cppcheck.settings().supprs.nomsg;
268268

269-
unsigned int returnValue;
269+
unsigned int returnValue = 0;
270270
if (settings.useSingleJob()) {
271271
// Single process
272272
SingleExecutor executor(cppcheck, mFiles, mFileSettings, settings, suppressions, stdLogger);
273273
returnValue = executor.check();
274274
} else {
275275
#if defined(THREADING_MODEL_THREAD)
276-
ThreadExecutor executor(mFiles, mFileSettings, settings, suppressions, stdLogger, CppCheckExecutor::executeCommand);
277-
#elif defined(THREADING_MODEL_FORK)
278-
ProcessExecutor executor(mFiles, mFileSettings, settings, suppressions, stdLogger, CppCheckExecutor::executeCommand);
276+
if (settings.executor == Settings::ExecutorType::Thread) {
277+
ThreadExecutor executor(mFiles, mFileSettings, settings, suppressions, stdLogger, CppCheckExecutor::executeCommand);
278+
returnValue = executor.check();
279+
}
280+
#endif
281+
#if defined(THREADING_MODEL_FORK)
282+
if (settings.executor == Settings::ExecutorType::Process) {
283+
ProcessExecutor executor(mFiles, mFileSettings, settings, suppressions, stdLogger, CppCheckExecutor::executeCommand);
284+
returnValue = executor.check();
285+
}
279286
#endif
280-
returnValue = executor.check();
281287
}
282288

283289
cppcheck.analyseWholeProgram(settings.buildDir, mFiles, mFileSettings);

cmake/compilerDefinitions.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ if (ENABLE_CHECK_INTERNAL)
4141
add_definitions(-DCHECK_INTERNAL)
4242
endif()
4343

44-
if (USE_THREADS)
45-
add_definitions(-DUSE_THREADS)
44+
if (ALLOW_THREAD_EXECUTOR)
45+
add_definitions(-DALLOW_THREAD_EXECUTOR)
4646
endif()
4747

4848
if (MSVC AND DISABLE_CRTDBG_MAP_ALLOC)

cmake/options.cmake

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,14 @@ if (BUILD_CORE_DLL)
5858
set(USE_BUNDLED_TINYXML2 ON)
5959
endif()
6060
option(CPPCHK_GLIBCXX_DEBUG "Usage of STL debug checks in Debug build" ON)
61-
option(USE_THREADS "Usage of threads instead of fork() for -j" OFF)
61+
option(ALLOW_THREAD_EXECUTOR "Allow usage of ThreadExecutor for -j" ON)
6262
option(USE_BOOST "Usage of Boost" OFF)
6363
option(USE_LIBCXX "Use libc++ instead of libstdc++" OFF)
6464

65+
if (NOT ALLOW_THREAD_EXECUTOR AND WIN32)
66+
message(FATAL_ERROR "Cannot disable usage of ThreadExecutor on Windows as no other executor implementation is currently available")
67+
endif()
68+
6569
option(DISABLE_CRTDBG_MAP_ALLOC "Disable usage of Visual Studio C++ memory leak detection in Debug build" OFF)
6670
option(NO_UNIX_SIGNAL_HANDLING "Disable usage of Unix Signal Handling" OFF)
6771
option(NO_UNIX_BACKTRACE_SUPPORT "Disable usage of Unix Backtrace support" OFF)

cmake/printInfo.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ if (HAVE_RULES)
7171
message( STATUS "PCRE_LIBRARY = ${PCRE_LIBRARY}" )
7272
endif()
7373
message( STATUS )
74-
message( STATUS "USE_THREADS = ${USE_THREADS}" )
74+
message( STATUS "ALLOW_THREAD_EXECUTOR = ${ALLOW_THREAD_EXECUTOR}" )
7575
message( STATUS "CMAKE_THREAD_LIBS_INIT = ${CMAKE_THREAD_LIBS_INIT}" )
7676
message( STATUS )
7777
message( STATUS "USE_BUNDLED_TINYXML2 = ${USE_BUNDLED_TINYXML2}" )

lib/config.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,11 @@ static const std::string emptyString;
153153
#if defined(_WIN32)
154154
#define THREADING_MODEL_THREAD
155155
#define STDCALL __stdcall
156-
#elif defined(USE_THREADS)
157-
#define THREADING_MODEL_THREAD
158-
#define STDCALL
159156
#elif ((defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)) || defined(__CPPCHECK__)
160-
#define THREADING_MODEL_FORK
157+
#define HAS_THREADING_MODEL_FORK
158+
#if defined(ALLOW_THREAD_EXECUTOR)
159+
#define HAS_THREADING_MODEL_THREAD
160+
#endif
161161
#define STDCALL
162162
#else
163163
#error "No threading model defined"

lib/settings.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@ const char Settings::SafeChecks::XmlExternalVariables[] = "external-variables";
3636

3737
Settings::Settings()
3838
{
39+
// TODO: set default executor
3940
severity.setEnabled(Severity::error, true);
4041
certainty.setEnabled(Certainty::normal, true);
4142
setCheckLevelNormal();
43+
executor = defaultExecutor();
4244
}
4345

4446
std::string Settings::loadCppcheckCfg()
@@ -589,3 +591,14 @@ std::string Settings::getMisraRuleText(const std::string& id, const std::string&
589591
const auto it = mMisraRuleTexts.find(id.substr(id.rfind('-') + 1));
590592
return it != mMisraRuleTexts.end() ? it->second : text;
591593
}
594+
595+
Settings::ExecutorType Settings::defaultExecutor()
596+
{
597+
static constexpr ExecutorType defaultExecutor =
598+
#if defined(HAS_THREADING_MODEL_FORK)
599+
ExecutorType::Process;
600+
#elif defined(HAS_THREADING_MODEL_THREAD)
601+
ExecutorType::Thread;
602+
#endif
603+
return defaultExecutor;
604+
}

lib/settings.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,18 @@ class CPPCHECKLIB WARN_UNUSED Settings {
192192
bool exceptionHandling{};
193193
#endif
194194

195+
enum class ExecutorType
196+
{
197+
#ifdef HAS_THREADING_MODEL_THREAD
198+
Thread,
199+
#endif
200+
#ifdef HAS_THREADING_MODEL_FORK
201+
Process
202+
#endif
203+
};
204+
205+
ExecutorType executor;
206+
195207
// argv[0]
196208
std::string exename;
197209

@@ -462,6 +474,8 @@ class CPPCHECKLIB WARN_UNUSED Settings {
462474
void setMisraRuleTexts(const std::string& data);
463475
std::string getMisraRuleText(const std::string& id, const std::string& text) const;
464476

477+
static ExecutorType defaultExecutor();
478+
465479
private:
466480
static std::string parseEnabled(const std::string &str, std::tuple<SimpleEnableGroup<Severity>, SimpleEnableGroup<Checks>> &groups);
467481
std::string applyEnabled(const std::string &str, bool enable);

man/cppcheck.1.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
117117
<arg choice="opt">
118118
<option>--errorlist</option>
119119
</arg>
120+
<arg choice="opt">
121+
<option>--executor=&lt;type&gt;</option>
122+
</arg>
120123
<arg choice="opt">
121124
<option>--exitcode-suppressions=&lt;file&gt;</option>
122125
</arg>
@@ -328,6 +331,15 @@ Example: '-UDEBUG'</para>
328331
<para>Print a list of all possible error messages in XML format.</para>
329332
</listitem>
330333
</varlistentry>
334+
<varlistentry>
335+
<term>
336+
<option>--executor=&lt;type&gt;</option>
337+
</term>
338+
<listitem>
339+
<para>Specifies the executor to use. Possible values:</para>
340+
<glosslist><glossentry><glossterm>auto</glossterm><glossdef><para>Automatically select (default)</para></glossdef></glossentry><glossentry><glossterm>thread</glossterm><glossdef><para>Perform analysis within a thread in the main process</para></glossdef></glossentry><glossentry><glossterm>proicess</glossterm><glossdef><para>Perform analysis of each file in a separate child process</para></glossdef></glossentry></glosslist>
341+
</listitem>
342+
</varlistentry>
331343
<varlistentry>
332344
<term>
333345
<option>--exitcode-suppressions=&lt;file&gt;</option>

releasenotes.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ Other:
2323
- Added '--template=simple'. It is expands to '{file}:{line}:{column}: {severity}:{inconclusive:inconclusive:} {message} [{id}]' without any additional location details.
2424
- Removed deprecated platform type 'Unspecified'. Please use 'unspecified' instead.
2525
- Removed deprecated 'Makefile' option 'SRCDIR'.
26+
- Added CMake option 'ALLOW_THREAD_EXECUTOR' to control the inclusion of the executor which performs the analysis within a thread of the main process.
27+
- Removed CMake option 'USE_THREADS' in favor of 'ALLOW_THREAD_EXECUTOR'.
28+
- Added command-line option `--executor=` to specify the executor. Available options are 'auto', 'process' and 'thread'. 'auto' will prefer 'process' if it is available. Note: Windows has no implementation of 'process' as of now so it will always chose 'thread' for now.

test/testcmdlineparser.cpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,21 @@ class TestCmdlineParser : public TestFixture {
338338
TEST_CASE(signedCharUnsignedChar);
339339
TEST_CASE(library);
340340
TEST_CASE(libraryMissing);
341+
TEST_CASE(executorDefault);
342+
TEST_CASE(executorAuto);
343+
TEST_CASE(executorAutoNoJobs);
344+
#if defined(HAS_THREADING_MODEL_THREAD)
345+
TEST_CASE(executorThread);
346+
TEST_CASE(executorThreadNoJobs);
347+
#else
348+
TEST_CASE(executorThreadNotSupported);
349+
#endif
350+
#if defined(HAS_THREADING_MODEL_FORK)
351+
TEST_CASE(executorProcess);
352+
TEST_CASE(executorProcessNoJobs);
353+
#else
354+
TEST_CASE(executorProcessNotSupported);
355+
#endif
341356

342357
TEST_CASE(ignorepaths1);
343358
TEST_CASE(ignorepaths2);
@@ -2282,6 +2297,87 @@ class TestCmdlineParser : public TestFixture {
22822297
ASSERT_EQUALS("cppcheck: Failed to load library configuration file 'posix2'. File not found\n", logger->str());
22832298
}
22842299

2300+
void executorDefault() {
2301+
REDIRECT;
2302+
const char * const argv[] = {"cppcheck", "file.cpp"};
2303+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv));
2304+
#if defined(HAS_THREADING_MODEL_FORK)
2305+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2306+
#elif defined(HAS_THREADING_MODEL_THREAD)
2307+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2308+
#endif
2309+
}
2310+
2311+
void executorAuto() {
2312+
REDIRECT;
2313+
const char * const argv[] = {"cppcheck", "-j2", "--executor=auto", "file.cpp"};
2314+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2315+
#if defined(HAS_THREADING_MODEL_FORK)
2316+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2317+
#elif defined(HAS_THREADING_MODEL_THREAD)
2318+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2319+
#endif
2320+
}
2321+
2322+
void executorAutoNoJobs() {
2323+
REDIRECT;
2324+
const char * const argv[] = {"cppcheck", "--executor=auto", "file.cpp"};
2325+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2326+
#if defined(HAS_THREADING_MODEL_FORK)
2327+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2328+
#elif defined(HAS_THREADING_MODEL_THREAD)
2329+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2330+
#endif
2331+
}
2332+
2333+
#if defined(HAS_THREADING_MODEL_THREAD)
2334+
void executorThread() {
2335+
REDIRECT;
2336+
const char * const argv[] = {"cppcheck", "-j2", "--executor=thread", "file.cpp"};
2337+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2338+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2339+
}
2340+
2341+
void executorThreadNoJobs() {
2342+
REDIRECT;
2343+
const char * const argv[] = {"cppcheck", "--executor=thread", "file.cpp"};
2344+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2345+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Thread, settings->executor);
2346+
ASSERT_EQUALS("cppcheck: '--executor' has no effect as only a single job will be used.\n", logger->str());
2347+
}
2348+
#else
2349+
void executorThreadNotSupported() {
2350+
REDIRECT;
2351+
const char * const argv[] = {"cppcheck", "-j2", "--executor=thread", "file.cpp"};
2352+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
2353+
ASSERT_EQUALS("cppcheck: error: executor type 'thread' cannot be used as Cppcheck has not been built with a respective threading model.\n", logger->str());
2354+
}
2355+
#endif
2356+
2357+
#if defined(HAS_THREADING_MODEL_FORK)
2358+
void executorProcess() {
2359+
REDIRECT;
2360+
const char * const argv[] = {"cppcheck", "-j2", "--executor=process", "file.cpp"};
2361+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(4, argv));
2362+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2363+
}
2364+
2365+
void executorProcessNoJobs() {
2366+
REDIRECT;
2367+
const char * const argv[] = {"cppcheck", "--executor=process", "file.cpp"};
2368+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
2369+
ASSERT_EQUALS_ENUM(Settings::ExecutorType::Process, settings->executor);
2370+
ASSERT_EQUALS("cppcheck: '--executor' has no effect as only a single job will be used.\n", logger->str());
2371+
}
2372+
#else
2373+
void executorProcessNotSupported() {
2374+
REDIRECT;
2375+
const char * const argv[] = {"cppcheck", "-j2", "--executor=process", "file.cpp"};
2376+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(4, argv));
2377+
ASSERT_EQUALS("cppcheck: error: executor type 'process' cannot be used as Cppcheck has not been built with a respective threading model.\n", logger->str());
2378+
}
2379+
#endif
2380+
22852381
void ignorepaths1() {
22862382
REDIRECT;
22872383
const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"};

0 commit comments

Comments
 (0)