I want to write a configuration file with qmake that #defines a few values. But I cannot simply create variables that contain the hash or pound character (#). Nonworking example:
lines = "/* Autogenerated: do not edit */"
if(foo): lines += "#define MYLIB_WITH_FOO 1"
else: lines += "#define MYLIB_WITH_FOO 0"
write_file(config.h, lines)
The hash starts a comment (inside the string!), so this won't work. How to generate the proper #defines for write_file under qmake?
There's a predefined variable called LITERAL_HASH specially created to deal with this problem.
If this name seems too long you can create one of your own:
H = $$LITERAL_HASH
lines = "/* Autogenerated: do not edit */"
if(foo): lines += "$${H}define MYLIB_WITH_FOO 1"
else: lines += "$${H}define MYLIB_WITH_FOO 0"
write_file(config.h, lines)
The trick is to use $$system() to create the hash character. This example works for me under Windows and Linux:
pound = $$system(printf $$system_quote(\43))
if(foo): lines += "$${pound}define MYLIB_WITH_FOO 1"
else: lines += "$${pound}define MYLIB_WITH_FOO 0"
It is usual on a C or C++ application sources to include a "config.h" header, that is generated by the buildsystem from a template (for instance "config.h.in"). This is available using autotools, and also CMake - see: configure_file(). But what about Qmake?
Here is an alternative using QMAKE_SUBSTITUTES. Another reference.
test.pro
TEMPLATE = app
QT = core
CONFIG += cmdline c++11
VERSION = 1.2.3
FOO = 1
QMAKE_SUBSTITUTES = config.h.in
SOURCES += main.cpp
DISTFILES += config.h.in
config.h.in
/* Autogenerated: do not edit */
#ifndef CONFIG_H
#define CONFIG_H
#define MYLIB_VERSION '"$$VERSION"'
#define MYLIB_BANNER '"Project version $$VERSION created with Qt $$QT_VERSION"'
#define MYLIB_WITH_FOO $$FOO
#endif // CONFIG_H
main.cpp
#include <QCoreApplication>
#include <QDebug>
#include "config.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << MYLIB_BANNER;
if (MYLIB_WITH_FOO) {
qDebug() << "Foo included!";
}
return 0;
}
Output:
Project version 1.2.3 created with Qt 5.12.5
Foo included!
Related
I have a C file <ask.c> :
int func(int i) {
return i;
}
int main() {
int i;
int j = func(i);
return j;
}
When I try to compiler ask.c by command <clang ask.c -Wall>, I get a warning like
ask.c:7:18: warning: variable 'i' is uninitialized when used here [-Wuninitialized]
int j = func(i);
^
ask.c:6:10: note: initialize the variable 'i' to silence this warning
int i;
^
= 0
1 warning generated.
Obviously this variable is indeed not initialized. When I went to explore how clang issued this warning, I found that it was through Diagnostics. The code of clang is as follows:
S.Diag(Use.getUser()->getBeginLoc(), diag::warn_uninit_var)
<< VD->getDeclName() << IsCapturedByBlock
<< Use.getUser()->getSourceRange();
define in Diagnostic*Kinds.td:
def warn_uninit_var : Warning<
"variable %0 is uninitialized when %select{used here|captured by block}1">,
InGroup<Uninitialized>, DefaultIgnore;
The exported information is output here, but what surprises me is that the source code of the error location is also output. How clang outputs the source code of the error location?
int j = func(i);
^
clang::Sema (your variable S in S.Diag) has access to the clang::SourceManager which in turn has access to all the raw bytes of all the input files, as well as non-files like macro expansion buffers expanded lazily if needed. The diagnostics printer uses the source manager interface to turn the clang::SourceLocation into file:line:col as well as a pointer to the raw bytes so it can print that line, as well as query the source manager to obtain the stack of macro instantiations or #include directives followed if applicable.
If I have a header-only library (Eigen in my case) like this:
cc_library(
name = "eigen",
hdrs = glob(
["Eigen/**"],
exclude = [
"Eigen/src/OrderingMethods/Amd.h",
"Eigen/src/SparseCholesky/**",
"Eigen/Eigen",
"Eigen/IterativeLinearSolvers",
"Eigen/MetisSupport",
"Eigen/Sparse",
"Eigen/SparseCholesky",
"Eigen/SparseLU",
],
),
defines = [
"EIGEN_MPL_ONLY",
"EIGEN_NO_DEBUG",
"EIGEN_DONT_PARALLELIZE",
"EIGEN_UNALIGNED_VECTORIZE=0",
"EIGEN_MAX_ALIGN_BYTES=32",
"EIGEN_MAX_STATIC_ALIGN_BYTES=32",
"EIGEN_NO_AUTOMATIC_RESIZING"
],
)
Are the defines observed at all, or do I have to manually add these defines to each dependend library?
additionally, say I have two libraries in my project that depend on Eigen, and I want to compile one with AVX512 and the other without. How can I hide the respective compiled eigen symbols from each other, so that it does not reuse the ones compiled with different defines?
A target that depedens on eigen will also inherit the defines (e.g. EIGEN_MPL_ONLY).
See for details here:
Each string, ..., is
prepended with -D and added to the compile command line to this
target, as well as to every rule that depends on it
A can also setup a small testbed to check how defines work:
WORKSPACE.bazel
# Empty
main/BUILD.bazel
cc_binary(
name = "main",
srcs = ["main.cpp"],
deps = ["//my_header_only_lib:my_header_only_lib"]
)
main/main.cpp
#include "header.h"
#include <iostream>
int main() {
Vector3<float> vec;
vec.print();
#ifdef FOO_BAR
std::cout << "FOO_BAR is also known in main" << std::endl;
#endif
}
my_header_only_lib/BUILD.bazel
package(
default_visibility = ["//visibility:public"],
)
cc_library(
name = "my_header_only_lib",
hdrs = ["header.h"],
includes=["."],
defines = ["FOO_BAR"],
)
my_header_only_lib/my_header_only_lib.h
#pragma once
#include <iostream>
template<typename ScalarType>
class Vector3 {
public:
ScalarType x, y, z;
void print() {
#ifdef FOO_BAR
std::cout << "FOO_BAR defined" << std::endl;
#endif
}
};
Output
FOO_BAR defined
FOO_BAR is also known in main
Flex sets the YY_STATE to INITIAL by default when yyscan_t is called.
I'm trying to make a reentrant scanner that can start with user-specific state instead of INITIAL.
Here is the case
/* comment start //not passed into flex
in comment //first line passed into flex
end of comment*/ //second line passed into flex
For some reasons these 2 lines are separately fed into the reentrant scanner and the YY_STATE the line belongs to are known. What I need is to pass the comment state into reentrant flex and switch YY_STATE to COMMENT before start lexing in comment\n.
My workaround are adding a dummy token in head of a line and passing the state as yyextra into flex. Once the dummy token is recognized, switch to the specific state. Hence flex begins lexing the line with specific YY_STATE. However, adding a dummy token at the beginning of each line is time-consuming.
Here is the way I used to call reentrant flex:
yyscan_t scanner;
YY_BUFFER_STATE buffer;
yylex_init(&scanner);
buffer = yy_scan_string(inputStr, scanner);
yyset_extra(someStructure, scanner);
yylex(scanner);
yy_delete_buffer(buffer, scanner);
yylex_destroy(scanner);
Is it possible to set YY_STATE before yylex(scanner) is called ?
If you are only calling yylex once for each input line, then you could just add an extra argument to yylex which provides the start condition to switch to, and set the start condition at the top of yylex.
But there's no simple way to refer to start conditions from outside of the flex file, nor is there a convenient way to extract the current start condition from the yystate_t object. The fact that you claim to have this information available suggests that you are storing it somewhere when you change start states, so you could restore the start state from that same place when you start up yylex. The simplest place to store the information would be the yyextra object, so that's the basis of this sample code:
File begin.int.h
/* This is the internal header file, which defines the extra data structure
* and, in this case, the tokens.
*/
#ifndef BEGIN_INT_H
#define BEGIN_INT_H
struct Extra {
int start;
};
enum Tokens { WORD = 256 };
#endif
File begin.h
/* This is the external header, which includes the header produced by
* flex. That header cannot itself be included in the flex-generated code,
* and it depends on the internal header. So the order of includes here is
* (sadly) important.
*/
#ifndef BEGIN_H_
#define BEGIN_H_
#include "begin.int.h"
#include "begin.lex.h"
#endif
File: begin.l
/* Very simple lexer, whose only purpose is to drop comments. */
%option noinput nounput noyywrap nodefault 8bit
%option reentrant
%option extra-type="struct Extra*"
%{
#include "begin.int.h"
/* This macro ensures that start condition changes are saved */
#define MY_BEGIN(s) BEGIN(yyextra->start = s)
%}
%x IN_COMMENT
%%
/* See note below */
BEGIN (yyextra->start);
"/*" MY_BEGIN(IN_COMMENT);
[[:alnum:]]+ return WORD;
[[:space:]]+ ;
. return yytext[0];
<IN_COMMENT>{
"*/" MY_BEGIN(INITIAL);
.|[^*]+ ;
}
Note:
Any indented code after the first %% and before the first pattern is inserted at the beginning of yylex; the only thing that executes before it is the one-time initialization of the yystate_t object, if necessary.
File begin.main.c
/* Simple driver which creates and destroys a scanner object for every line
* of input. Note, however, that it reuses the extra data object, which holds
* persistent information (in this case, the current start condition).
*/
#include <stdio.h>
#include "begin.h"
int main ( int argc, char * argv[] ) {
char* buffer = NULL;
size_t buflen = 0;
struct Extra my_extra = {0};
for (;;) {
ssize_t nr = getline(&buffer, &buflen, stdin);
if (nr < 0) break;
if (nr == 0) continue;
yyscan_t scanner;
yylex_init_extra(&my_extra, &scanner);
/* Ensure there are two NUL bytes for yy_scan_buffer */
if (buflen < nr + 2) {
buffer = realloc(buffer, nr + 2);
buflen = nr + 2;
}
buffer[nr + 1] = 0;
YY_BUFFER_STATE b = yy_scan_buffer(buffer, nr + 2, scanner);
for (;;) {
int token = yylex(scanner);
if (token == 0) break;
printf("%d: '%s'\n", token, yyget_text(scanner));
}
yy_delete_buffer(b, scanner);
yylex_destroy(scanner);
}
return 0;
}
Build:
flex -o begin.lex.c --header-file begin.lex.h begin.l
gcc -Wall -ggdb -o begin begin.lex.c begin.main.c
#include<stdio.h>
#define engine_exhaust_gas_temperature_raw 100
#define engine_exhaust_gas_temperature_scaled 20
#define Sum(x, y) ( ( x )+ ( y ) )
int main(){
printf("%d",engine_exhaust_gas_temperature_raw);
return 0;
}
I am working on MISRA C Rule 5.4 Macro identifiers shall be distinct for which I need the list of the names of all the macros defined in a C program as strings.
For ex: In the above code I will need:
[ "engine_exhaust_gas_temperature_raw", "engine_exhaust_gas_temperature_scaled", "Sum"]
Is there any way to get this list using clang AST?
I have found that we can use clangs https://clang.llvm.org/doxygen/classclang_1_1Preprocessor.html Preprocessor class to get the iterator to macros but even this is not producing any output for me. I have used it in the below code. What am I missing here?
bool distinct_macro_identifier(CompilerInstance *C_I, ASTContext *Context){
auto st= C_I->getPreprocessor().macro_begin()->getFirst()->getName();
auto x= C_I->getPreprocessor().macro_begin()->first;
llvm::outs()<<x->getName()<<"\n";
auto p= C_I->getPreprocessor().getMacroInfo(x);
p->dump();
return true;
}
You can compile it with this command:
clang++ -E -dM -nostdlib file.cpp
How to use Cling in my app via API to interpret C++ code?
I expect it to provide terminal-like way of interaction without need to compile/run executable. Let's say i have hello world program:
void main() {
cout << "Hello world!" << endl;
}
I expect to have API to execute char* = (program code) and get char *output = "Hello world!". Thanks.
PS. Something similar to ch interpeter example:
/* File: embedch.c */
#include <stdio.h>
#include <embedch.h>
char *code = "\
int func(double x, int *a) { \
printf(\"x = %f\\n\", x); \
printf(\"a[1] in func=%d\\n\", a[1]);\
a[1] = 20; \
return 30; \
}";
int main () {
ChInterp_t interp;
double x = 10;
int a[] = {1, 2, 3, 4, 5}, retval;
Ch_Initialize(&interp, NULL);
Ch_AppendRunScript(interp,code);
Ch_CallFuncByName(interp, "func", &retval, x, a);
printf("a[1] in main=%d\n", a[1]);
printf("retval = %d\n", retval);
Ch_End(interp);
}
}
There is finally a better answer: example code! See https://github.com/root-project/cling/blob/master/tools/demo/cling-demo.cpp
And the answer to your question is: no. cling takes code and returns C++ values or objects, across compiled and interpreted code. It's not a "string in / string out" kinda thing. There's perl for that ;-) This is what code in, value out looks like:
// We could use a header, too...
interp.declare("int aGlobal;\n");
cling::Value res; // Will hold the result of the expression evaluation.
interp.process("aGlobal;", &res);
std::cout << "aGlobal is " << res.getAs<long long>() << '\n';
Apologies for the late reply!
Usually the way one does it is:
[cling$] #include "cling/Interpreter/Interpreter.h"
[cling$] const char* someCode = "int i = 123;"
[cling$] gCling->declare(someCode);
[cling$] i // You will have i declared:
(int) 123
The API is documented in: http://cling.web.cern.ch/cling/doxygen/classcling_1_1Interpreter.html
Of course you can create your own 'nested' interpreter in cling's runtime too. (See the doxygen link above)
I hope it helps and answers the question, more usage examples you can find under the test/ folder.
Vassil