I want to be able to get the current source file path.
string txt_file = CURRENT_FILE_PATH +"../../txt_files/first.txt";
inFile.open(txt_file .c_str());
Is there a way to get the CURRENT_FILE_PATH ?
I don't mean the executable path. I mean the current location of the source file that the code is running from.
Thanks a lot,
Giora.
The path used to compile the source file is accessible through the standard C macro __FILE__ (see http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html)
If you give an absolute path as input to your compiler (at least for gcc) __FILE__ will hold the absolute path of the file, and vice versa for relative paths. Other compilers may differ slightly.
If you are using GNU Make and you list your source files in the variable SOURCE_FILES like so:
SOURCE_FILES := src/file1.cpp src/file2.cpp ...
you can make sure the files are given by their absolute path like so:
SOURCE_FILES := $(abspath src/file1.cpp src/file2.cpp ...)
C++20 source_location::file_name
We now have another way besides __FILE__, without using the old C preprocessor: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf
The documentation simply says:
constexpr const char* file_name() const noexcept;
5 Returns: The presumed name of the current source file (14.2) represented
by this object as an NTBS.
where NTBS means "Null Terminated Byte String".
I'll give it a try when support arrives to GCC, GCC 9.1.0 with g++-9 -std=c++2a still doesn't support it.
https://en.cppreference.com/w/cpp/utility/source_location claims usage will be like:
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const std::source_location& location std::source_location::current()
) {
std::cout << "info:"
<< location.file_name() << ":"
<< location.line() << ":"
<< location.function_name() << " "
<< message << '\n';
}
int main() {
log("Hello world!");
}
Possible output:
info:main.cpp:16:main Hello world!
Related
I have tried working with the command line arguments in a small C++ program on Amiga 1200 (Workbench 3.1.4).
I have compiled with the use of bebbo’s cross-compiler g++ (m68k-amigaos-g++) (see https://github.com/bebbo/amiga-gcc) a simple CLI app that just outputs the arguments. While it works fine when compiled with 'normal' g++ in Windows, it failed in AmigaShell in Amiga Forever emulator and Amiga 1200 machine as well.
I have found on some forums that the preprocessor symbol __stdargs should be used, which as I understand instructs the compiler to handle the generated assembler as if the function was called with the parameters passed on stack and not with the use of registers. Is that correct understanding?
Is the normal that Amiga (and g++) by default use registers and it needs to be overridden for AmigaShell? I added that to __stdargs to the main() function. Anyway, that did not help.
Next, I have read, again on some forum, that -mcrt parameter has to be used when compiler output is linked. I have struggled to find the purpose do the parameter. It seems it specifies which standard C library (similar to glibc) to be linked? According the Google the following possible variants of the parameter (-mcrt=nix13, -mcrt=nix20, and mcrt=clib2) (see e.g. https://github.com/adtools/libnix).
The only one that works fine was nix20 (nix13 did not link and clib2 linked, but the program did not work on Amiga. Why in a first-place we need the standard C library?
I have used this with -mcrt: m68k-amigaos-g++ args.o -mcrt=nix20 -o args and it finally worked:
Can anybody describe to me as a newbie a bit more background details of all this?
Here is my test program:
#include <iostream>
using std::cout;
#if defined (__AMIGA__)
#define MAIN_FNC __stdargs
#else
#define MAIN_FNC
#endif
MAIN_FNC int main( int argc, char *argv[] )
{
cout << "Arguments count:" << argc << " \n";
for ( int i = 0; i < argc; i ++ )
cout << i << ". [" << argv[i] << "]\n";
return 0;
}
You don't need any MAIN_FNC, remove it. Also don't need to play with -mcrt=xxx. Just link with -noixemul option.
m68k-amigaos-g++ args.o -noixemul -o args
By default ixemul.library is used/linked (in short and very simply the ixemul.library emulate some unix behavior, see here). That cause your problem.
More info about -noixemul related to gcc & AmigaOS here:
GCC and ixemul.library
I have below sample code which I ran on visual studio 2019 and on https://godbolt.org/. I can see that there are two different behavior. What could be the possible reason ?
#include <iostream>
#include <filesystem>
int main()
{
std::filesystem::path p("//net");
std::cout << "root name of " << p << " is " << p.root_name() << std::endl;
}
Output in visualstudio 2019 : root name of "//net" is "//net"
Output in https://godbolt.org/ : root name of "//net" is ""
I Just read http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4100.pdf - 8.4.9 path decomposition [path.decompose]
but did not understand the reason.
Also, I read below code in the std::filesystem but din not understand completely
_NODISCARD path root_name() const {
// parse the root-name from *this and return a copy if present; otherwise, return the empty path
return _Parse_root_name(_Text);
}
Is there anyone who can explain me in more detail to understand the problem ?
Compiler Explorer runs most of its compilers on a POSIX system. POSIX allows an implementation to interpret a leading //foo similarly to how Windows interprets a leading \\foo: as a host name for a network filesystem. (Windows actually supports either kind of slash, as seen in your example.) However, modern implementations do not do this (relying instead on automounting in some directory like /net), so //foo just means /foo, which like everything else is under the one Unix root directory /. filesystem::path doesn’t count that global root as having a name in the sense of \\host or C: from Windows.
I am trying to compile the regex part of the boost C++ library on AIX using the xlC compiler and use it as a 64-bit dynamic library, because I need to compare the performance of several C++ regex libraries and built-in solutions, and boost seemed like a viable candidate.
Here are my exact OS and compiler versions:
$ uname -a
AIX host_name 1 7 00F9A2144C00
$ xlC -qversion
IBM XL C/C++ for AIX, V13.1.2 (5725-C72, 5765-J07)
Version: 13.01.0002.0000
Since I do not have root priviliges, I cannot actually install the boost library, I am only trying to compile the regex part into a shared object file and to obtain all of the needed headers for my test application. I have tried to compile the latest available version (1.59.0), and also version 1.55.0, because I found that IBM has released a source code patch for boost:
http://www-01.ibm.com/support/docview.wss?uid=swg27042921
I compile boost and copy the headers and the shared object file to my development folder using the following commands:
bootstrap.sh --with-toolset=vacpp --prefix=/my/user/directory --exec-prefix=/my/user/directory
./b2 address-model=64 cxxflags=-q64 cflags=-q64
b2 tools/bcp
./dist/bin/bcp boost/regex.hpp /my/include/directory
cp stage/lib/libboost_regex.so /my/library/directory
I know i could add the --with-libraries=regex flag to compile only the regex part, but it is irrelevant to my problems.
With both versions, with or without patching the boost source code, I encounter the same problems.
First: I already have some libraries compiled, and linked to my simple test application, for example the PCRE C++ regex library. When I also try to link the boost regex library, with the -lboost_regex compile flag, I get the following error:
ld: 0706-006 Cannot find or open library file: -l boost_regex
ld:open(): No such file or directory
make: The error code from the last command is 255.
This is resolved by adding the -brtl compile flag, which as far as I know would only be needed if I would try to link a static library, so it looks like to me as if libboost_regex.so would actually be libboost_regex.a
Second: When I add the line #include "boost/regex.hpp" to my code, I get a compilation error:
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 217.19: 1540-0130 (S) "false_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 223.19: 1540-0130 (S) "true_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 229.19: 1540-0130 (S) "true_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 235.19: 1540-0130 (S) "true_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 244.11: 1540-0130 (S) "false_type" is not declared.
"/opt/IBM/xlC/13.1.2/include/xtr1common", line 250.11: 1540-0130 (S) "true_type" is not declared.
make: The error code from the last command is 1.
My test application is really simple. These are the contents of my Makefile:
all:
/opt/IBM/xlC/13.1.2/bin/xlC -q64 -Iinclude -Llibs -lpcrecpp main.cpp -o regexp_test
clean:
rm regexp_test
Here is the source code of my very basic test application:
#include <iostream>
#include <string.h>
#ifndef __IBMCPP_TR1__
#define __IBMCPP_TR1__ 1
#include <regex>
#undef __IBMCPP_TR1__
#endif
#define __IBMCPP_TR1__ 1
/* Regular expression libraries to be included */
#include <sys/types.h>
#include <regex.h>
#include "pcrecpp.h"
// #include "boost/regex.hpp"
#include "deelx.h"
int main(int argc, char **argv)
{
if(argc != 4){
std::cerr << "Use: ./regexp_test <posix|tr1|pcre|deelx> value regexp" << std::endl;
return 1;
}
int status;
char buffer[256], regexp[256];
snprintf(buffer,sizeof(buffer),argv[2]);
snprintf(regexp,sizeof(regexp),argv[3]);
std::string buffer_string = buffer;
bool match = false;
if(strcmp(argv[1],"posix")==0){
regex_t comp;
if (regcomp(&comp, regexp, REG_EXTENDED) != 0) {
std::cerr << "The regular expression '" << regexp << "' could not be compiled!" << std::endl;
return 1;
} else {
status = regexec(&comp, buffer, (size_t) 0, NULL, 0);
regfree(&comp);
if (status == 0) {
match = true;
}
}
} else if(strcmp(argv[1],"tr1")==0){
try {
std::tr1::smatch matches;
std::tr1::regex rgx(regexp);
status = std::tr1::regex_search(buffer_string, matches, rgx);
if(status){
match = true;
}
}
catch(std::tr1::regex_error& re)
{
std::cerr << "TR1 exception caught!" << std::endl;
}
} else if(strcmp(argv[1],"pcre")==0){
pcrecpp::RE re(regexp);
if(re.PartialMatch(buffer)){
match = true;
}
} else if(strcmp(argv[1],"deelx")==0){
static CRegexpT <char> deelx_regexp(regexp, IGNORECASE | MULTILINE);
MatchResult result = deelx_regexp.Match(buffer);
if(result.IsMatched()){
match = true;
}
} else {
std::cerr << "Use: ./regexp_test <posix|tr1|pcre|deelx> value regexp" << std::endl;
return 1;
}
if (!match) {
std::cout << "The regular expression '" << regexp << "' does NOT match the value '" << buffer << "'." << std::endl;
} else {
std::cout << "The regular expression '" << regexp << "' matches the value '" << buffer << "'." << std::endl;
}
return 0;
}
How can these problems be resolved? Any hints or advice would be appreciated.
I have found a soltuion for both of my problems.
The problem with linking:
I have found this post:
https://web.archive.org/web/20100514132209/http://durgaprasad.wordpress.com/2006/09/28/problems-with-linking-of-shared-libraries-in-aix/
Problems with linking of shared libraries in AIX September 28, 2006 at
8:13 am (AIX, C/C++)
Normally, in Solaris, Linux and other common platforms, shared libraries are represented with .so/.sl suffix. Static libraries are
represented with .a suffix in filenames. But in AIX, static libraries
have .a suffix and shared libraries can have either .so or .a suffix.
when we try to compile a c file which uses shared library with .so
suffix, it wont succeed by default. It gives a compilation error.
Additionally we have to pass “-Wl,-brtl” flag to the compiler. “-Wl”
is to say that it is a flag to the linker, so “-brtl” is internally
passed to the linker [ld]. “-brtl” says that it should consider files
with .so suffix also as shared libraries. There is no need to pass
this flag when your shared library contains .a suffix. This type of
linking is loadtime linking.
When we want to access a shared library at runtime using dlopen &
dlsym calls, it is called runtime linking. In this case, we wont get
any compilation errors. If the shared library contains .a suffix, we
wont get any errors at runtime also. But if the shared library
contains .so suffix, we get segmentation fault at runtime. Confusing
thing is, it succesfully executes dlopen call, but at the time of
dlsym, it exits with segmentation fault. If we give “-Wl-brtl” flag to
compiler at compilation time, runtime linking goes fine.
It details that on AIX, shared libraries can have both .so and .a suffix, and to instruct the compiler to search for .so files you'll need to include the -brtl flag. It also instructs to include the -Wl flag, in order to pass the linkage flags directly to the linker (ld), but I have found that with this version of xlC this functionality is deprecated.
The problem with the code:
The preprocessor instruction #define __IBMCPP_TR1__ 1 caused the boost regex library to fail with a compilation error. This define was only needed for the built-in tr1 regular expressions of AIX I am also using, but it turns out it is only required for the #include <regex> part, I can omit the second define.
I have a file module.hpp
struct ModuleBase {
virtual void run() = 0;
};
and a main.cpp program
int main() {
cout << ...?...; // here should go the contents of module.hpp
}
What can I put at ...?... to let the contents of the header file printed here?
A basic idea would be
int main() {
static const string content = R"(
#include <module.hpp>
)";
cout << content;
}
but multi-line-strings are only available in C++11, and #include does not work inside multi-line strings (which is good)?
If there is a non-portable way for the gcc... that would be a start.
Clarification (update): The substitution should be done at compile time.
The only real solution I know is to write a small program which
converts a file into a C++ definition of a string variable
containing it. This is fairly simple to write: output a simple
header along the lines of:
char const variableName[] =
Then copy each line of the file, wrapping it in "...\n", and
escaping any characters necessary. (If you can be sure of
C++11, then you might be able to do something with R"...", but
I've no experience with this.)
[update: refering to the original question with a typo in it]:
Your solution should not work; if it does, it is an error in
the compiler. According to §2.2, tokenization occurs before
the execution of preprocessing directives. So when the
execution of preprocessing directives occurs, you have a string
literal, and not a # preprocessing token. (Compiler errors
are to be expected when using C++11 features. There's not been
enough time yet for the implementers to get all of the bugs
out.)
As a GNU-only hack, you could convert the header into a binary object file and link that with the executable.
First, use objcopy to do the conversion:
objcopy -I binary -O default -B i386 module.hpp module.hpp.o
replacing i386 with the architecture you're building for if necessary. The resulting object file will contain symbols for the header contents and its size, which you can access as follows:
#include <iostream>
extern char _binary_module_hpp_start;
extern char _binary_module_hpp_size;
int main()
{
char * header_start = &_binary_module_hpp_start;
size_t header_size = reinterpret_cast<size_t>(&_binary_module_hpp_size);
std::cout.write(header_start, header_size);
}
Apart from external tools, I think it cannot be done. The C++11 way you given does not work, #include is not expanded in a string. See here for example.
The C++03 way would have been the following, with macros:
#define TO_STR__(...) #__VA_ARGS__
#define TO_STR_(...) TO_STR__(__VA_ARGS__)
#define TO_STR(...) TO_STR_(__VA_ARGS__)
#include <iostream>
int main()
{
std::cout << "String from #include <string>, ";
static const char* str = TO_STR(
#include <string>
);
std::cout << sizeof(str) / sizeof(char) << " characters:\n\n";
std::cout << str << "\n";
}
With GCC, nothing is outputed. With Visual Studio 2010, #include <string> is outputed.
If you can modify the compilation chain, you can add a prebuild step which will include the contents of the file you want as a string (can be done easily with tools like CMake, or custom makefile).
You can use ofstream to open a file stream and read and output the contents.
Presuming that your C++ compiler supports them, is there any particular reason not to use __FILE__, __LINE__ and __FUNCTION__ for logging and debugging purposes?
I'm primarily concerned with giving the user misleading data—for example, reporting the incorrect line number or function as a result of optimization—or taking a performance hit as a result.
Basically, can I trust __FILE__, __LINE__ and __FUNCTION__ to always do the right thing?
__FUNCTION__ is non standard, __func__ exists in C99 / C++11. The others (__LINE__ and __FILE__) are just fine.
It will always report the right file and line (and function if you choose to use __FUNCTION__/__func__). Optimization is a non-factor since it is a compile time macro expansion; it will never affect performance in any way.
In rare cases, it can be useful to change the line that is given by __LINE__ to something else. I've seen GNU configure does that for some tests to report appropriate line numbers after it inserted some voodoo between lines that do not appear in original source files. For example:
#line 100
Will make the following lines start with __LINE__ 100. You can optionally add a new file-name
#line 100 "file.c"
It's only rarely useful. But if it is needed, there are no alternatives I know of. Actually, instead of the line, a macro can be used too which must result in any of the above two forms. Using the boost preprocessor library, you can increment the current line by 50:
#line BOOST_PP_ADD(__LINE__, 50)
I thought it's useful to mention it since you asked about the usage of __LINE__ and __FILE__. One never gets enough surprises out of C++ :)
Edit: #Jonathan Leffler provides some more good use-cases in the comments:
Messing with #line is very useful for pre-processors that want to keep errors reported in the user's C code in line with the user's source file. Yacc, Lex, and (more at home to me) ESQL/C preprocessors do that.
FYI: g++ offers the non-standard __PRETTY_FUNCTION__ macro. Until just now I did not know about C99 __func__ (thanks Evan!). I think I still prefer __PRETTY_FUNCTION__ when it's available for the extra class scoping.
PS:
static string getScopedClassMethod( string thePrettyFunction )
{
size_t index = thePrettyFunction . find( "(" );
if ( index == string::npos )
return thePrettyFunction; /* Degenerate case */
thePrettyFunction . erase( index );
index = thePrettyFunction . rfind( " " );
if ( index == string::npos )
return thePrettyFunction; /* Degenerate case */
thePrettyFunction . erase( 0, index + 1 );
return thePrettyFunction; /* The scoped class name. */
}
C++20 std::source_location
C++ has finally added a non-macro option, and it will likely dominate at some point in the future when C++20 becomes widespread:
https://en.cppreference.com/w/cpp/utility/source_location
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1208r5.pdf
The documentation says:
constexpr const char* function_name() const noexcept;
6 Returns: If this object represents a position in the body of a function,
returns an implementation-defined NTBS that should correspond to the
function name. Otherwise, returns an empty string.
where NTBS means "Null Terminated Byte String".
The feature is present on GCC 11.2 Ubuntu 21.10 with -std=c++20. It was not on GCC 9.1.0 with g++-9 -std=c++2a.
https://en.cppreference.com/w/cpp/utility/source_location shows usage is:
main.cpp
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const std::source_location& location = std::source_location::current()
) {
std::cout << "info:"
<< location.file_name() << ":"
<< location.line() << ":"
<< location.function_name() << " "
<< message << '\n';
}
int main() {
log("Hello world!");
}
Compile and run:
g++ -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out
Output:
info:main.cpp:17:int main() Hello world!
__PRETTY_FUNCTION__ vs __FUNCTION__ vs __func__ vs std::source_location::function_name
Answered at: What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__?
Personally, I'm reluctant to use these for anything but debugging messages. I have done it, but I try not to show that kind of information to customers or end users. My customers are not engineers and are sometimes not computer savvy. I might log this info to the console, but, as I said, reluctantly except for debug builds or for internal tools. I suppose it does depend on the customer base you have, though.
I use them all the time. The only thing I worry about is giving away IP in log files. If your function names are really good you might be making a trade secret easier to uncover. It's sort of like shipping with debug symbols, only more difficult to find things. In 99.999% of the cases nothing bad will come of it.