I'm writing code in C++ and I need to read a file, problem is my file structure is a bit complex and I just cannot figure out how to use my ifstream to read it. I think I tried all possible combinations... but it just doesn't work, I guess I'm doing something wrong but I can't figure it out.
Here is a minimal reproduction of my problem.
structure :
.
├── build
├── CMakeLists.txt
└── src
├── file
│ └── test.txt
├── load
│ └── loadfile.hpp
└── main.cpp
CMakeLists.txt :
cmake_minimum_required(VERSION 3.10)
project(BaseProject)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-O3 -g -std=c++17 -Wall -Wextra -pedantic")
file(GLOB SRC
"src/*.h"
"src/*.hpp"
"src/load/*.h"
"src/load/*.hpp"
"src/load/*.cpp"
)
add_executable(exec ${SRC} src/main.cpp)
main.cpp
#include "load/loadfile.hpp"
int main(){
load();
return 0;
}
test.txt : (not very relevent but meh)
test
loadfile.hpp
#include <fstream>
#include <string>
#include <iostream>
void loadFile(const std::string& file){
std::ifstream i(file, std::ifstream::in);
std::string str;
i >> str;
std::cerr << str;
i.close();
}
void load(){
loadFile("../file/test.txt");
}
output is empty and program finishes normally.
This might help, when you call install your files will be copied to destination specified.
cmake_minimum_required(VERSION 3.10)
project(BaseProject)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-O3 -g -std=c++17 -Wall -Wextra -pedantic")
set(OUTPUT_DIR "Yours to fill, working dir")
file(GLOB RESOURCES "./file/test.txt")
file(GLOB SRC
"src/*.h"
"src/*.hpp"
"src/load/*.h"
"src/load/*.hpp"
"src/load/*.cpp"
)
add_executable(exec ${SRC} src/main.cpp)
install (FILES ${RESOURCES} DESTINATION ${OUTPUT_DIR})
Answer from Some programmer dude in the comments:
Now might be a good time to learn about the concept of current working
directory. When you run a program, its process will have a current
working directory. If you run from a console or terminal then it's
usually the terminals current directory. Relative paths (paths not
beginning with a /) are always relative to the current working
directory. You need to make sure that the relative path in the program
is valid for the programs current working directory when running.
Related
I'm making a game engine in C++ with CMake, I have the following directory structure:
Engine/
│ CMakeLists.txt
|
├─ lib/
| libengine.a
|
├─ example/
│ │ CMakeLists.txt
| |
│ ├─ bin/
| | example
| |
│ └─ source/
│ └─ Example.cxx
|
├─ include/
│ Engine.hxx
|
└─ source/
Engine.cxx
I've used this directory structure in a few other projects and it was ok until I encountered a problem, when I write to a file through the program it creates it in the 'Engine' directory, but I want it to create the file in 'Engine/example/bin/' (where the executable is) without any modifications to the C++ code. The same goes for reading files. At first I though this was because Engine::SaveGame() was in the engine library, so I tried to create a file through fstream in main but I got the same result.
Here are the cmake build scripts and the C++ source:
Engine/CMakeLists.txt:
cmake_minimum_required(VERSION 3.22)
project("Engine" LANGUAGES CXX)
message(STATUS "Running CMakeLists.txt for Engine")
option(LIB_BUILD_EXAMPLE "Build the example" ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-m64 -s -O3 -Wall -Wextra")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY lib/)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY lib/)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY lib/)
add_library(engine STATIC
source/Engine.cxx
)
target_include_directories(engine PUBLIC
include/
)
if(LIB_BUILD_EXAMPLE)
add_subdirectory(example)
endif()
Engine/include/Engine.hxx:
#pragma once
namespace Engine {
extern void SaveGame();
} // namespace Engine
Engine/source/Engine.cxx:
#include "Engine.hxx"
#include <iostream>
#include <fstream>
namespace Engine {
void SaveGame() {
printf("Saving game...\n");
std::ofstream output_file("game1.sav");
output_file << "game data";
}
} // namespace Engine
Engine/example/CMakeLists.txt:
cmake_minimum_required(VERSION 3.22)
project("Example" LANGUAGES CXX)
message(STATUS "Running CMakeLists.txt for Example")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_FLAGS "-m64 -s -Wall -Wextra")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY bin/)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY bin/)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY bin/)
add_executable(example
source/Example.cxx
)
target_link_libraries(example
engine
)
Engine/example/Example.cxx:
#include "Engine.hxx"
#include <fstream>
int main() {
Engine::SaveGame();
std::ofstream output_file("test.txt");
output_file << "line 1\nline 2\n";
return 0;
}
The way I build this project is by running cmake . and then make in the 'Engine' directory, and I run the example to test the engine by doing ./example/bin/example.
I think this has to do with some CMake option or something.
I am compiling an application using CMake 3.16.3 and G++ 9.3 on Ubuntu 20.04. This is the current source directory:
. (this is called MyApp)
├── src
│ ├── /* source files */
│ └── CMakeLists.txt
├── tests
│ ├── /* source files */
│ └── CMakeLists.txt
├── build-release
│ └── pgo /* folder for .gcda files */
├── build_release.sh
└── CMakeLists.txt*
I am setting the flags in CMakeLists.txt (the root one also marked with asterisk) as follows:
set(MYAPP_PGO "-fprofile-dir=${MYAPP_PGO} -fprofile-generate=${MYAPP_PGO}")
// apply flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG -O3 -march=native -flto ${MYAPP_PGO}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MYAPP_PGO}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MYAPP_PGO}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MYAPP_PGO}")
add_subdirectory(src)
add_subdirectory(tests)
No flags are being set in src/CMakeLists.txt and tests/CMakeLists.txt.
MYAPP_PGO is set in bash and is the absolute path of build-release/pgo. I have a script (build_release.sh) that builds the program:
# excluded other lines and flags for brevity
cd build-release
cmake -DMYAPP_PGO="$(pwd)/pgo/" ..
make -j1
After the profile run, I see that there are multiple files in build-release/pgo, one for each cpp file in src and test, such as
#home#johndoe#MyApp#build-release#src#CMakeFiles#MYAPPLICATION_myapp.dir#sample_source.cpp.gcda
However, when compiling again with
// this is a multithreaded program
set(MYAPP_PGO "-fprofile-dir=${MYAPP_PGO} -fprofile-use=${MYAPP_PGO} -fprofile-correction")
// apply flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNDEBUG -O3 -march=native -flto ${MYAPP_PGO}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MYAPP_PGO}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MYAPP_PGO}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MYAPP_PGO}")
add_subdirectory(src)
add_subdirectory(tests)
I get a warning stating that there are missing profile files:
/home/johndoe/MyApp/src/sample_source.cpp: In function ‘_GLOBAL__sub_I_sample_source.cpp’:
/home/johndoe/MyApp/src/sample_source.cpp:215:1: warning: ‘/home/johndoe/MyApp/src/sample_source.cpp/build-release/pgo//#home#johndoe#MyApp#build-release#src#CMakeFiles#MYAPPLICATION_myapp.dir#sample_source.cpp.gcda’ profile count data file not found [-Wmissing-profile]
215:1 refers to the last character in this source file.
I have tested the speed of the program with and without PGO and have seen no improvement. Although PGO is not guaranteed to bring any speed ups, I tend to believe that PGO did not work as expected here. Am I doing something wrong?
For anyone wondering...
I did not write the original build system of the project. I discovered that it compiled one executable and one library from the same source. Whilst the executable was profiled and recompiled successfully (PGO was done flawlessly), the library was not used anywhere. Hence the missing profile files. Because the profiler outputs extremely long names, I thought the error came from the executable. Thank you all for the help.
I have such files
.
├── CMakeLists.txt
└── src
├── CMakeLists.txt
└── main.c
And this is the content about this files
$ cat CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
PROJECT (HELLO)
ADD_SUBDIRECTORY(src bin)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/binarydir)
$ cat src/CMakeLists.txt
ADD_EXECUTABLE(hello main.c)
$ cat src/main.c
#include <stdio.h>
int main()
{
printf("Hello World from t1 main().\n");
return 0;
}
Then I build it with following command
$ mkdir build
$ cd build
$ cmake ..
$ make
This is the result directory structure
Then the binary hello will produced in directory build/bin as the picture, but it should be in build/binarydir since I have set the value for EXECUTABLE_OUTPUT_PATH, isn't it? What I have missed?
You are creating executable target before setting EXECUTABLE_OUTPUT_PATH. Move SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/binarydir) line before ADD_SUBDIRECTORY(src bin).
I'm trying to load an external OpenCL kernel and the clCreateKernel returns an error code: -46 CL_INVALID_KERNEL_NAME. The file structure is the following:
.
├── CMakeLists.txt
└── src
├── cl.hpp
├── GameOfLife.cpp
└── kernels
└── programs.cl
This is my first CMake project, thus I'm not sure the following CMake is correct:
cmake_minimum_required(VERSION 3.5)
project(gpgpu_gameoflife)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lOpenCL")
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/src/kernels)
# source: http://igorbarbosa.com/articles/how-to-use-opengl-freeglut-and-cmake/
#########################################################
# FIND GLUT
#########################################################
find_package(GLUT REQUIRED)
include_directories(${GLUT_INCLUDE_DIRS})
link_directories(${GLUT_LIBRARY_DIRS})
add_definitions(${GLUT_DEFINITIONS})
if(NOT GLUT_FOUND)
message(ERROR " GLUT not found!")
endif(NOT GLUT_FOUND)
#########################################################
# FIND OPENGL
#########################################################
find_package(OpenGL REQUIRED)
include_directories(${OpenGL_INCLUDE_DIRS})
link_directories(${OpenGL_LIBRARY_DIRS})
add_definitions(${OpenGL_DEFINITIONS})
if(NOT OPENGL_FOUND)
message(ERROR " OPENGL not found!")
endif(NOT OPENGL_FOUND)
set(SOURCE_FILES
src/GameOfLife.cpp
src/kernels/programs.cl
)
add_executable(gpgpu_gameoflife ${SOURCE_FILES})
target_link_libraries(gpgpu_gameoflife ${OPENGL_LIBRARIES} ${GLUT_LIBRARY})
For the following function call I get an empty string as a result, thus I think the kernel file is not available to be read (the kernel itself is not empty).
std::string sourceCode = fileToString("kernels/programs.cl");
...
std::string fileToString(const std::string &path) {
std::ifstream file(path, std::ios::in | std::ios::binary);
if (file) {
std::ostringstream contents;
contents << file.rdbuf();
file.close();
return (contents.str());
}
return "";
}
Could you please tell me how to create an OpenCL application using CMake that loads an external kernel? Or is this not a good practice?
Thank you!
Although the following line in CMake solves my problem, I'm still waiting for other answers maybe containing a better solution.
configure_file(src/kernels/programs.cl kernels/programs.cl COPYONLY)
you should update your path depending from where you build your program
If your project looks like this:
── CMakeLists.txt
└── src
| ├── cl.hpp
| ├── GameOfLife.cpp
| └── kernels
| └── programs.cl
└── build
and you call "make" from the build directory, the string path should look like this: "../src/kernels/programs.cl". Alternatively you can set a CMake variable with "set(PATH_TO_FILE "${CMAKE_SOURCE_DIR}/src/kernels/programs.cl") and pass it to the main args
Going through the CMake tutorial:
├── CMakeLists.txt
├── src
│ └── main.cpp
└── templates
└── fooConf.h.in
CMakeLists.txt
cmake_minimum_required(VERSION 3.2)
project(foo)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(PROJECT_SOURCE_DIR src)
set(PROJECT_TEMPLATE_DIR templates)
set(SOURCE_FILES ${PROJECT_SOURCE_DIR}/main.cpp)
set(${PROJECT_NAME}_MAJOR 0)
set(${PROJECT_NAME}_MINOR 1)
set(${PROJECT_NAME}_MICRO 1)
configure_file (
"${PROJECT_TEMPLATE_DIR}/fooConf.h.in"
"${PROJECT_SOURCE_DIR}/fooConf.h"
)
add_executable(foo ${SOURCE_FILES})
templates/fooConf.h.in
#define #PROJECT_NAME#_VERSION_MAJOR #PROJECT_NAME##_VERSION_MAJOR#
#define #PROJECT_NAME#_VERSION_MINOR #PROJECT_NAME##_VERSION_MINOR#
#define #PROJECT_NAME#_VERSION_MICRO #PROJECT_NAME##_VERSION_MICRO#
src/main.cpp
#include <iostream>
#include "src/fooConf.h"
// Also tried: "fooConf.h"
int main() {
std::cout << foo_VERSION_MAJOR;
return 0;
}
[Error]
fatal error: src/fooConf.h: No such file or directory
Your fooConf.h header file is generated in the binary tree (precisely, under ${CMAKE_BINARY_DIR}/src/). So you should issue corresponded include_directories() command for use that file in #include. E.g.:
CMakeLists.txt
....
include_directories(${CMAKE_BINARY_DIR})
add_executable(foo ${SOURCE_FILES})
src/main.cpp
....
#include "src/fooConf.h"