C++ command line debug argument - c++

How can I change the value of a boolean macro when I run my program through the command line? For instance, suppose I have the following macro in my cpp file, call it MyCpp.cpp
#define DEBUG 1
How can I change this when I run my program? through the command line:
g++ -Wall -Wextra -o MyCpp MyCpp.cpp
I am pretty sure you specify some kind of command line option, does this ring any bells?
Also, I do NOT want to use argv[]

First, change your source code:
#ifndef DEBUG
# define DEBUG 1
#endif
Now you can say on the command line:
g++ -Wall -Wextra -o MyCpp MyCpp.cpp -DDEBUG=5
# ^^^^^^^^^
The command line argument -DFOO=bar has the same effect as putting #define FOO bar in your source code; you need the #ifndef guard to avoid an illegal redefinition of the macro.
Sometimes people use an auxiliary macro to prevent the definition of another macro:
#ifndef SUPPRESS_FOO
# define FOO
#endif
// ... later
#ifdef FOO
// ...
#endif
Now say -DSUPPRESS_FOO to not define FOO in the code...

How can I change the value of a boolean macro when I run my program through the command line?
As it stands, you can't. You are using a preprocessor symbol so the decision as to whether debug information should be printed is a compile time decision. You are going to have to change that compile-time DEBUG symbol to a run-time variable that you set by parsing the command line, via some configuration file read in at run time, or both.
Parsing the command line isn't that hard. There are plenty of low-level C-style tools to help you do that. Boost has a much more powerful C++ based scheme. The trick then is to change those compile-time debug decisions to run-time decisions. At the simplest, it's not that hard: Just replace that DEBUG preprocessor symbol with a global variable. You can get quite a bit more sophisticated than this of course. Eventually you'll have a configurable logging system. Boost has that, too.

Please note the following. If you have in your c/cpp file or one of your included header files:
#define DEBUG 1
then you cannot modify this definition using the command line of the compiler (makefile). There is simply no chance. The cpp file will simply overwrite the command line setting.

Related

Having difficulties compiling simple c++ program on the command line with multiple files; maybe a linker error?

Sorry for the simple question. I am attempting to learn more c++ at a fundamental level. I have always used VS in the past, and I am trying to learn the command line and compile, navigate, etc. with it.
I started with "hello world" and was able to compile it with gcc/clang, then run it with the expected results.
I then slightly reworked this and made a new header/cpp file to do the output part of hello world, and then call that from the main function, described below:
main.cpp:
#include "MyClass.h"
int main(){
foo();
return 0;
}
MyClass.h
#pragma once
void foo();
MyClass.cpp
#include "MyClass.h"
#include <iostream>
void foo(){
std::cout << "Hello World\n";
}
I then have tried to compile with gcc and clang as follows:
clang -Wall -g main.cpp MyClass.cpp
I have tried the same with GCC, and have also tried various invocations of this, such as using -c:
clang -Wall -g -c main.cpp
clang -Wall -g -c MyClass.cpp
Each and every time, I get an error
λ clang -Wall -g MyClass.cpp main.cpp
main.cpp:13:1: error: use of undeclared identifier 'foo'
foo();
^
1 error generated.
I get this same error whether using gcc or clang.
I also tried from scratch on my laptop, to see if there was some more global issue, but I still get the same problem.
I have also tried on the basic Windows command line as well.
Other areas on StackOverflow demonstrate simple ways of compiling multiple files from the command line, and I have tried as they show, but still get errors.
I also know that "make" is something I need to learn as well, however, I just want to make sure I understand what my make file is doing before I dive into that.
I feel like it must be something trivial that I just cannot figure out.
Thank you to Andreas for the suggestion of looking at the preprocessor output. And thank you to everyone for the suggestions.
The pre-processor output did not make sense to what I was compiling.
I was using VSCode, in this case, as a text editor, making brand new files in my folder after launching it from the command line. I thought the files I created in VSCode directly into the folder (named main.cpp, for example), would produce a regular text file. However, for some reason, it did not.
Essentially, I recreated the above program in notepad and was easily able to compile it using the commands I used above. I guess VSCode may not be perfect for me as a pure text editor or I should figure out if there are settings to change to accomplish my goal.
Thank you all again for your time and consideration.
Use extern on your function. Also make sure you're compiling with c++ and not c; i.e. g++.
MyClass.h
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
extern void foo();
#ifdef __cplusplus
}
#endif

What kind of code is in that file *.cpp.. #define mdTyVzgFy4_0UFy9GimmM

I just downloaded an open source code from a library called aruco for QR code detection written in C++, and while I was examing the code I found some files that doesn't look like c++..
Would anyone understand what kind of code is that? It looks like that
#define mUXyv8dbk5ppT_acPhWw1 mFzTZaNOrvPJ32i9gU3Wr9J28M8DBzQ(a,:,[,+,c,+,:,^,Z,Z,/,-,r,O,[,;,9,e,;,P)
#define mmdgJNaGE2dbCM6TccQ56 mkzSZJDew824aa0gKauM6fZ2VRvPUyZ(^,Q,5,r,j,P,t,B,c,;,T,A,o,W,},u,*,e,7,/)
#define mVBw_rTkATYMOTRmsNe_B mGJoExPsp9LQpgvTNdOhH4AqaFjFPrq(+,W,4,t,i,o,d,2,e,P,1,A,:,a,E,S,v,F,Y,V)
#define mH9xkXr1In9WhMDYLLAkQ mhN2hPhnFFq5alNSwVOjtfx8xECWu2g(R,r,R,z,t,2,i,b,!,k,S,n,e,C,k,K,5,o,K,a)
#define mSye5PefiM2uFq__QqZRQ m_dk3EP_dRaChCeAYkjUT4mGB6eHLjG(s,Y,^,r,*,P,D,X,y,^,b,},k,4,a,=,i,X,!,v)
#define mJpQJFURUc57_1UwCTPvr mByXC_NAGVGzCcmUEv_c9mAYK8t5jBN(t,R,.,>,!,i,W,0,R,C,*,Y,A,>,K,h,T,-,*,8)
#define my9E4sAt6II28meWefBqO mu1aRcYPGwwmkdvLrXjWyYkshrNbQfZ(8,N,+,t,},r,I,T,=,C,*,h,!,m,{,/,D,y,_,T)
#define mRtPBvwiZzHWglctKPmaF msiqIfe8Aci2FIHOTIR3qsdKyqc9jUO(7,i,j,^,_,^,6,},I,<,E,-,/,d,j,=,:,N,+,s)
#endif
#ifndef _ARUCO_MarkerDetector_Impl_H
#define _ARUCO_MarkerDetector_Impl_H
#include "aruco_export.h"
#include "markerdetector.h"
#include <opencv2/imgproc/imgproc.hpp>
mH83V9yQZ4TlJHtn2Baef
aruco
mBduW7dqSuFrUAvwh7kHo
mTj14DRd7xgEPvsp5xhPs
CameraParameters mVlbuMLWi_vwpED0hDKIw
mrJuVHPe96ExiggCdsmDG
MarkerLabeler mv0LWHXRSvGJF76ckeLfO
mPXYuzTL9RZjjZA9XYUV9
MarkerDetector_Impl
mYwjl00gOK3Vja3UkLMIP
friend mukY8albO2VdJSsWPXwW4
MarkerDetector mD07x3flmZMPVC6kwqG6P
public:
MarkerDetector_Impl mnODdIJiXbJxgUNOnnK7Q
mYCDBBfn03HaGvoHBxAMq
MarkerDetector_Impl mK8B3zN6mQAB0xYXFlxGO
int dict_type, mYJJZNT6RsQUQcGvcjw6s
error_correction_rate mRUhvrauugCIk8ZFUtFF5
0 mswZzmsb_awITT3YY34kR
What kind of code is in that file *.cpp.. #define mdTyVzgFy4_0UFy9GimmM
#define mdTyVzgFy4_0UFy9GimmM is a pre-processor directive that defines a macro. Macros are used to replace text during pre-processing.
Would anyone understand what kind of code is that?
Probably no human can understand it. And that is probably the reason why that has been done in the first place: It seems to be an attempt to obfuscate the source code.
You can use a pre-processor to generate the processed code to see what the compiler sees. For example, gcc -E. Note that the pre-processor will expand the include directives, so you'll need to scroll past the included files first.
Would anyone understand what kind of code is that?
Yes! Wow this is fun. That is indeed an obfuscated source code.
It is still C/C++. It is using pre-processor definitions. Basically it is a key that can be used multiple times. (like a variable).
The compiler will search for all preprocessor definitions and replaces them by the actual text.
I guess you want to deobfuscate it to have a closer look in the source code.
For gcc and clang, you can use the -E option (see similar answer) to output the preprocessor output without compiling.
To also show comments like in your sample output, you can add in the -CC and -P flags:
clang++ -E -CC -P fileA.cpp
All of the processor options for -E can be found on here, on
gcc.gnu.org.
-CC Do not discard comments, including during macro expansion. This is like -C, except that comments contained within macros are also passed
through to the output file where the macro is expanded.
-P Inhibit generation of linemarkers in the output from the preprocessor. This might be useful when running the preprocessor on
something that is not C code, and will be sent to a program which
might be confused by the linemarkers.
For the Visual C++ compiler, you can use /E.

g++: Is there a way to access compile flags inside the code that is being compiled?

Is there a way (e.g., defined constants) to access compile flags with which the compiler was run inside the code that is being compiled.
For example, I want a program that writes the flags with which it was compiled.
int main(){
std::cout << COMPILE_FLAGS << std::endl;
}
Do such constants exist for gcc/g++? Or even better: Are there constants that are defined both in gcc and clang?
I am especially interested in examining the optimization level and the value of the -march flag. So, if there are no constants that show all flags, are there at least ones that display these values?
The following command prints out all predefined macros:
g++ -dM -E - < /dev/null
This works with both gcc and g++. You can check yourself - unfortunately, there is no macro, that gives easy access to the full gcc/g++ command line.
Fortunately, most -m... flags result in adequate precompiler macros to be defined. For example, -m64 defines __x86_64 and -m32 defines __code_model_32__ . Or for -march: -march=core-avx2 results in #define __core_avx2__ 1 .
Just add the option, that you need to check, on the command line above, and check the result for new macro defines.
If you are able to change the compile flags or the script that generates the compilation command, you could add a -DCOMPILE_FLAGS=<the flags you are interested in> to your build to actually create that constant.
From the GCC manual:
-D name=definition The contents of definition are tokenized and processed as if they appeared during translation phase three in a
‘#define’ directive. In particular, the definition will be truncated
by embedded newline characters.

How to find out cl.exe's built-in macros

Does anyone know how could I find out which are cl.exe's builtin/predefined macros?
For example for gcc the following command line will list all the compiler's builtin macros
gcc -dM -E - </dev/null
EDIT: I'm interested in a way similar to gcc's that is "ask the actual compiler".
Thanks
This method does amount to asking the compiler for the list of predefined macros, but it uses undocumented features and provides only a partial list. I include it here for completeness.
The Microsoft C/C++ compiler allows an alternative compiler front-end to be invoked using the /B1 and /Bx command line switches for .c and .cpp files respectively. The command-line interface module CL.exe passes a list of options to the replacement compiler front-end via the MSC_CMD_FLAGS environment variable. This list of options includes -D macro definitions for some of the predefined macros.
The following trivial replacement compiler front-end prints out the list of options passed to it:
/* MyC1.c */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p;
if ((p = getenv("MSC_CMD_FLAGS")) != NULL)
printf("MSC_CMD_FLAGS:\n%s\n", p);
if ((p = getenv("MSC_IDE_FLAGS")) != NULL)
printf("MSC_IDE_FLAGS:\n%s\n", p);
return EXIT_FAILURE;
}
Compile this to an executable named, for example, "MyC1.exe", ensure it is visible in the PATH and tell CL.exe to invoke it as the compiler front-end using one of the following:
cl /B1MyC1.exe AnyNameHere.c
cl /BxMyC1.exe AnyNameHere.cpp
Include other command-line options as required to see which macros are predefined for that set of options.
In the resulting output look for the -D options. An example list is given below. In the actual output the list will be space-separated, with each macro definition preceded by -D, and other options also present.
_MSC_EXTENSIONS
_INTEGRAL_MAX_BITS=64
_MSC_VER=1600
_MSC_FULL_VER=160030319
_MSC_BUILD=1
_WIN32
_M_IX86=600
_M_IX86_FP=0
_MT
This technique seems to include most macros that depend on command-line options, but excludes those that are always defined such as __FILE__ and __DATE__.
/P preprocessor flag will emit the currently active macros based on the project build settings. I am not sure if it is exactly the equivalent of gcc command you have shown. The output is in .I file.
Try the predef project. They maintain a database of predefined macros for many target platforms, host platforms and compiler toolchains.
They also have a script that attempts to discover all of the predefined names whether documented or not. It works by running the strings utility over the compiler, processing that to get plausible candidate tokens, and trying test compilations for each token. Not fast, but pretty good at discovering lots of macros.
I don't know in what version this was made available.
/PD print all macro definitions
Example use:
Create an empty file foo.cpp (e.g. echo // > foo.cpp)
cl /Zc:preprocessor /PD foo.cpp
Get information at the source!
http://msdn.microsoft.com/en-us/library/b0084kay%28v=VS.90%29.aspx
The available pre-defined C/C++ macros in MSVC, when using cl for compilation, depends (of course) on what you are compiling (C vs C++) and the variants for that, including architecture and other cl options. (Check your options with cl /help for additional info.)
Then the powershell (one-liner) commands are:
# For C++
echo // > foo.cpp; cl /nologo /Zc:preprocessor /PD /EHs /TP foo.cpp |sort; rm foo.cpp, foo.obj
# For C
echo // > foo.cpp; cl /nologo /Zc:preprocessor /PD /EHs /TC foo.cpp |sort; rm foo.cpp, foo.obj
For example, the output for C is:
#define __STDC_HOSTED__ 1
#define _INTEGRAL_MAX_BITS 64
#define _IS_ASSIGNABLE_NOCHECK_SUPPORTED 1
#define _M_AMD64 100
#define _M_X64 100
#define _MSC_BUILD 0
#define _MSC_EXTENSIONS 1
#define _MSC_FULL_VER 192930147
#define _MSC_VER 1929
#define _MSVC_EXECUTION_CHARACTER_SET 1252
#define _MSVC_TRADITIONAL 0
#define _MSVC_WARNING_LEVEL 1L
#define _MT 1
#define _WIN32 1
#define _WIN64 1
foo.cpp
LINK : fatal error LNK1561: entry point must be defined
If you wanna do the same trickery for using gcc in powershell, you need to use something like this:
echo `EOF` | gcc -E -dM -xc++ - |sort
As of Visual C++ 16.8.0, there is such an option. See https://developercommunity.visualstudio.com/t/provide-the-ability-to-list-predefined-macros-and/934925. Pass /EP /Zc:preprocessor /PD to the compiler along with an empty (or non-empty) source file. The option requires use of the "new" preprocessor.

What is the best way to eliminate MS Visual C++ Linker warning : "warning LNK4221"?

I have a CPP source file that uses #if / #endif to compile out completely in certain builds. However, this generates the following warning.
warning LNK4221: no public symbols found; archive member will be inaccessible
I was thinking about creating a macro to generate a dummy variable or function that wouldn't actually be used so this error would go away but I want to make sure that it doesn't cause problems such as using the macro in multiple files causing the linker to bomb on multiply defined symbols.
What is the best way to get rid of this warning (without simply suppressing the warning on the linker command line) ?
FWIW, I would be interested in knowing how to do it by suppressing the warning on the linker command line as well but all my attempts there appear to be simply ignored by the linker and still generate the error.
One other requirement: The fix must be able to stand up to individual file builds or unity build (combine CPP file builds) since one of our build configurations is a bulk build (like a unity build but groups of bulk files rather than a single master unity file).
Use an anonymous namespace:
namespace { char dummy; };
Symbols within such namespace have external linkage, so there will be something in the export table. On the other hand, the namespace name itself will be distinct (you can think of it as "randomly generated") for every translation unit, so no clashes.
OK, the fix I am going to use is Pavel's suggestion with a minor tweak. The reason I’m using this fix is it’s an easy macro to drop in and it will work in bulk-builds / unity-builds as well as normal builds:
Shared Header:
// The following macro "NoEmptyFile()" can be put into a file
// in order suppress the MS Visual C++ Linker warning 4221
//
// warning LNK4221: no public symbols found; archive member will be inaccessible
//
// This warning occurs on PC and XBOX when a file compiles out completely
// has no externally visible symbols which may be dependant on configuration
// #defines and options.
#define NoEmptyFile() namespace { char NoEmptyFileDummy##__LINE__; }
File that may compile out completely:
NoEmptyFile()
#if DEBUG_OPTION
// code
#endif // DEBUG_OPTION
(Though the discussion is already old and I cannot comment directly #Adisak's answer), I guess some additional macro expansion magic is needed for this to work:
#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define NONEMPTY_TRANSLATION_UNIT char TOKENPASTE2(NoEmptyFileDummy, __LINE__);