C++ CodeBlocks upgrade to C++17 can't use std::filesystem - c++

I need to be able to list the files in a directory, and so I'm trying to upgrade my C++ version in CodeBlocks to C++ 17 so i can use filesystem. To do this I followed the steps outlined at http://candcplusplus.com/enable-c17-in-code-blocks-mingw-gcc-for-all-version-with-pictures#:~:text=Enabling%20the%20C%2B%2B17,Create%20a%20project.
I didnt have to change much, CodeBlocks 20.03 and MinGW 8.1.0 are already installed. MinGW is already in my path from when I built wxWidgets. The Settings->Compiler...->Toolchain executables tab I didnt have to make any changes to, and appears in CodeBlocks as:
I also checked the box to use C++ 17 in compiler settings like so
I ran the test program on the website with the instructions and got "True!".
However when I change the basic test program to this, to try and use filesystem to read files in a directory, I get an error:
#include <iostream>
#include <filesystem>
using namespace std;
int main()
{
const int i=90;
if constexpr (i) //'if constexpr' is part of C++17
{
cout << "True!";
}
else
{
cout<<"False" ;
}
std::string path = "../MagicProgCPP/files/debug images/";
for (const auto & entry : filesystem::directory_iterator(path))
{
cout << entry.path() << std::endl;
}
cin.get();
return 0;
}
The program stops building, opens the file fs_path.h and stops on this line:
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (__p.is_absolute()
|| (__p.has_root_name() && __p.root_name() != root_name())) <----- ******STOPS HERE
operator=(__p);
else
{
string_type __pathname;
if (__p.has_root_directory())
__pathname = root_name().native();
else if (has_filename() || (!has_root_directory() && is_absolute()))
__pathname = _M_pathname + preferred_separator;
__pathname += __p.relative_path().native(); // XXX is this right?
_M_pathname.swap(__pathname);
_M_split_cmpts();
}
#else
// Much simpler, as any path with root-name or root-dir is absolute.
if (__p.is_absolute())
operator=(__p);
else
{
if (has_filename() || (_M_type == _Type::_Root_name))
_M_pathname += preferred_separator;
_M_pathname += __p.native();
_M_split_cmpts();
}
#endif
return *this;
}
I get this error in the build log:
C:\Program Files\CodeBlocks\MinGW\lib\gcc\x86_64-w64-mingw32\8.1.0\include\c++\bits\fs_path.h|237|error: no match for 'operator!=' (operand types are 'std::filesystem::__cxx11::path' and 'std::filesystem::__cxx11::path')|
I'm prety confident the path exists as I entered it and there's files in it. The build log message suggests maybe I'm not using C++17? But when I click build, this is the line the program uses to build:
g++.exe -Wall -fexceptions -g -Wall -std=c++17 -c E:\testc17\main.cpp -o obj\Debug\main.o
What am I doing wrong? Thanks

The bug 78870 was fixed since 2018-07.
You should add to project options -> linker settings -> link libraries the following library: stdc++fs.
I tried to compile your code with MinGW gcc 8.1.0 (via CodeBlocks) and everything works well (clearly with another path, since I don't have the same directories as you).
You could also add a check on the existence of the search directory like this:
namespace fs = std::filesystem;
std::string mypath { "../MyDir" };
if(fs::exists(mypath))
{
for(const auto & entry : fs::directory_iterator(path))
{
cout << entry.path() << std::endl;
}
}

It appears that this exact problem is a known bug in mingw 8.1. The bug report is here: https://sourceforge.net/p/mingw-w64/bugs/737/
and has the error in the same location:
operator != is declared and defined in line 550, but referenced in line 237.
The problem is triggered by operator/= in line 233:
path& operator/=(const path& __p)
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (__p.is_absolute()
|| (__p.has_root_name() && __p.root_name() != root_name()))
operator=(__p);
else
{
string_type __pathname;
if (__p.has_root_directory())
__pathname = root_name().native();
else if (has_filename() || (!has_root_directory() && is_absolute()))
__pathname = _M_pathname + preferred_separator;
__pathname += __p.relative_path().native(); // XXX is this right?
_M_pathname.swap(__pathname);
_M_split_cmpts();
}
The bug report said this was fixed in master meaning you need to install a version of mingw with the fix applied. I believe the best method is to upgrade mingw to a version greater than 8.1
user4581301 commented above in the main question that the following link has instructions on how to get a mingw install: How to install MinGW-w64 and MSYS2?

Related

Properly setting up tinycc with visual studio 2019, library libtcc1-32.a not found

I'm using tcclib to compile and run C code on the fly in my C++ project.
I'm using the binaries provided here https://bellard.org/tcc/
I then open a vs2019 developer prompt and run both those command
lib /def:libtcc\libtcc.def /out:libtcc.lib
cl /MD examples/libtcc_test.c -I libtcc libtcc.lib
My code builds fine, I'm using this code. This code is similar to the one found in the tcclib example, which is this one : https://repo.or.cz/tinycc.git/blob/HEAD:/tests/libtcc_test.c (this is another repo, but it's the same code.
The code I run is this one. This is inside an extern "C" {}.
int tcc_stuff(int argc, const char** argv) {
TCCState* s;
int i;
int (*func)(int);
s = tcc_new();
if (!s) {
fprintf(stderr, "Could not create tcc state\n");
exit(1);
}
/* if tcclib.h and libtcc1.a are not installed, where can we find them */
for (i = 1; i < argc; ++i) {
const char* a = argv[i];
if (a[0] == '-') {
if (a[1] == 'B')
tcc_set_lib_path(s, a + 2);
else if (a[1] == 'I')
tcc_add_include_path(s, a + 2);
else if (a[1] == 'L')
tcc_add_library_path(s, a + 2);
}
}
/* MUST BE CALLED before any compilation */
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
{
const char* other_file = ReadFile2(argv[1]);
if (other_file == NULL)
{
printf("invalid filename %s\n", argv[1]);
return 1;
}
if (tcc_compile_string(s, other_file) == -1)
return 1;
}
/* as a test, we add symbols that the compiled program can use.
You may also open a dll with tcc_add_dll() and use symbols from that */
tcc_add_symbol(s, "add", add);
tcc_add_symbol(s, "hello", hello);
/* relocate the code */
if (tcc_relocate(s, TCC_RELOCATE_AUTO) < 0)
return 1;
/* get entry symbol */
func = (int(*)(int))tcc_get_symbol(s, "foo");
if (!func)
return 1;
/* run the code */
msg(func(32));
//msg(func2(4));
/* delete the state */
tcc_delete(s);
return 0;
}
When running my code, TCC had the error
tcc: error: library 'libtcc1-32.a' not found
I fixed it by placing this file in the lib/ directory next to my .exe
I also copied the include/ folder to include stdio.h etc.
My question is: why does it need this file in a lib/ folder, instead of the provided tcclib.dll file? Is it possible to "ship" certain headers like stdio.h?
The question has no answer but 360 views, so I thought I'd reply.
The library doesn't necessarily need to be in that folder. To quote the author's command line docs, which still apply to the library,
-Ldir
Specify an additional static library path for the -l option. The default library paths are /usr/local/lib, /usr/lib and /lib.
I inferred your program to be a modified main() of libtcc_test.c & fixed it to the point of functioning. Then I used VS2022 to retrace your steps, put the .a files into the same folder as my new tests_libtcc_test.exe, then I ran this:
tests_libtcc_test c:/lang/tcc/examples/fib.c -Ic:/lang/tcc/include -L.
The library issue appears if I don't -L anything, and disappears if I include at least the ".".
And of course, you can drop the include folder into your redistributable and include it by default right from the code.
Because the tcc DLL is just another interface to the same compiler, it needs the same things tcc.exe would to build an executable; in this case, it needs the same libraries.

error is coming while compiling cpp file with linaro toolchain

I am trying to cross-compile openmcu-ru with linaro toolchain ,I am getting error in compiling conference.cxx file
It compiled correctly in ubuntu using gcc toolchain
but getting error with linaro toolchain
Following is error
conference.cxx:1503:6: error: prototype for 'void
ConferenceMember::Dial(PBoolean)' does not match any in class
'ConferenceMember' void ConferenceMember::Dial(BOOL _autoDial)
Following is code
////////////////////////////////////////////////////////////////////////////////////////////////////
#define BOOL PBoolean
BOOL autoDial ;
void ConferenceMember::Dial()
{
Dial(autoDial);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ConferenceMember::Dial(BOOL _autoDial) // **Line no. 1503**
{
if(IsSystem())
return;
PWaitAndSignal m(dialMutex);
autoDial = _autoDial;
if((autoDial && (OpenMCU::Current().autoDialDelay < 20)) || IsOnline())
return;
MCUH323EndPoint & ep = OpenMCU::Current().GetEndpoint();
if(dialToken != "" && ep.HasConnection(dialToken))
return;
dialToken = ep.Invite(conference->GetNumber(), GetName());
}
Regards
got the solution
changing BOOL to int in line 1503

Listing all files of a directory using C++ in Linux is not working

I used following code.
dp = opendir( dir.c_str() );
while ((dirp = readdir( dp )))
{
filepath = dir + "/" + dirp->d_name;
}
But dirp->d_name value is as follows.
.\000\000\000\004\324E\020\000\000\000\000\000\324!+^S\361Tf\030\000\004..\000\000\004\237X\n\000\000\000\000\000fJ\035\224\321M\264l(\000\bFontTest1.pdf\000\000\000\000\000\000\000\b\236X\n\000\000\000\000\000\377\377\377\377\377\377\377\177(\000\bproject_report.pdf\000\000\b
Are you perhaps mis-handling the "." and ".." dirs? (every dir has them)
I excluded them with:
std::string fn(ent->dname);
if(fn == ".") { if(dbg2) { std::cout << "S_DOT" << std::endl; } continue;}
if(fn == "..") { if(dbg2) { std::cout << "D_DOT" << std::endl; } continue;}
... prior to handling the various d_types
switch(ent->d_type)
{
case DT_UNKNOWN: {...}
case DT_DIR: {...}
// ... etc
}
The "continue" jumped to the beginning of the loop processing dirent entries.
The best cross platform way to do this is if you have the filesystem library. Unfortunately that's still a Technical Specification right now, so you'll need to either use Boost's version of this library or: experimental/filesystem.
Once you have filesystem though you can simply use a directory_iterator:
copy(directory_iterator(dir), directory_iterator(), ostream_iterator<path>(cout, "\n"))
That example may have been a bit complex. If I can clarify something for you let me know.
In Visual Studio 2015 this code runs if you simply #include <filesystem> and do using namespace tr2::sys. Unfortunately gcc 5.3 hasn't implemented directory_iterator.operator++() yet, so you'll need Boost there or you'll get an error along the lines of:
Undefined reference to std::experimental::filesystem::v1::__cxx11::directory_iterator::operator++()
Thanks all. I am able to sort it out by adding following code.
unsigned char isFile =0x8;
if ( dirp->d_type == isFile)
//process it

Linker error when compiling a program that uses spidermonkey

I've been trying to learn spidermonkey and so have written the following code, adapted from this guide and while the program compiles properly, I get the following error during linking:
/usr/bin/ld: cannot open linker script file symverscript: No such file or directory
I'm using 64-bit Ubuntu 13.10, and here is the code (seems irrelevant to the problem, but can't hurt)
#include <jsapi.h>
#include <iostream>
#include <string>
int main()
{
std::string script = "var x = 10;x*x;";
jsval rval;
JSRuntime* runtime = 0;
JSContext* context = 0;
JSObject* globalob = 0;
if((!(runtime = JS_NewRuntime(1024L*1024L, JS_NO_HELPER_THREADS)))||
(!(context = JS_NewContext(runtime, 8192)))||
(!(globalob = JS_NewObject(context, NULL, NULL, NULL))))
{
return 1;
}
if(!JS_InitStandardClasses(context, globalob))
{
return 1;
}
if(!JS_EvaluateScript(context,globalob,script.data(),script.length(),"script",1,&rval))
{
return 1;
}
std::cout << JSVAL_TO_INT(rval) << "\n";
JS_DestroyContext(context);
JS_DestroyRuntime(runtime);
JS_ShutDown();
return 0;
}
compiled with the command
g++ main.cpp -o out $(js24-config --cflags --libs | tr "\n" " ")
Try to write this command instead,
g++ main.cpp -o main -I/usr/local/include/js/ -L/usr/local/lib/ -lmozjs1.8.5
regarding the path I wrote above, you must write your own path which include the library and JSAPI.h file included in,
And the last term is spidermonkey library, you will find it in lib folder, for me it exists in /usr/local/lib

SDL 2.0 compiles, but failt to run

Im using the latest SDL 2.0 version on Xubuntu 64-bits. I installed through the provided install script on the source code.
Compiling works well, however when trying to open a font or image (regardless of its extension), it will always fail to open.
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
int main (int argc, char *argvp[])
{
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
cout << SDL_GetError() << endl;
}
if (TTF_Init() == -1)
{
std::cout << TTF_GetError() << std::endl;
return 2;
}
TTF_Font *font1 = NULL;
font1 = TTF_OpenFont("SourceSansPro-Regular.ttf", 20);
if (font1 == NULL)
{
std::cout << "ERROR OPENING FONT = " << TTF_GetError() << std::endl;
}
TTF_CloseFont(font1);
SDL_Quit();
return 0;
}
I compiled with
g++ -Wall fontTEST.cpp -o TEST -lSDL2 -lSDL_ttf (NOTE that SDL_ttf installs as such, not as SDL2_ttf)
And get the following error: Failed to load font: 0 Couldn't load font file
This happens with images as well. I've already tried with different fonts and images, apparently it works if I compile with SDL 1.2, just not with 2.0.
Also why does the provided install script installs the lib and include folders in /user/local/?
I moved them to /usr/ but the problem persists.
Remember the following:
On Unix, file paths are case-sensitive
As said in Xonar's comment, tilde '~' expansion is a shell feature, it does not work in C/C++ programs, you should use the real path instead.
The strace log says clearly that something is wrong with the path.
You should try the following:
Rename your font file to "font.ttf"
put it in /home/user/font.ttf
use "/home/user/font.ttf" as the path in your code.