I just found out i've been doing this wrong for the whole time. I haven't used any ide and only use gcc. I have started using makefile also to compile my large project.
most of the time the file structure was this
├── makefile
└── src
├── folder1
│ ├── header1.cpp
│ └── header1.h
├── folder2
│ ├── header2.cpp
│ └── header2.h
└── main.cpp
on header2.cpp, when I include header1.h I do it like this
file header2.cpp
#include "../folder1/header1.h"
this is how I include the other files from another folder.
I think I am doing wrong. most of the tutorial I have watch uses Ide and they don't include it like that.
some include it like this
#include "folder1/header1.h"
or others put it in a one folder like headers/
then include it like this.
#include "header1.h"
Can anyone guide me. how do i achieve this. I been doing this bad including I guess.
I don't want to include files like this
#include "../../../../sofarfolder1/header1.h"
thanks. it makes me puke everytime I see my code.
You can use the -Idir flag to tell GCC to look for header files in the directory dir, if you don't want to use ../.
More info: https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html
https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html
In your makefile, you can invoke gcc with -I../../../sofardirectory
That way, it will look in that directory for headers you include.
An unusual alternative to using compiler flags to specify additional include directories is to use the C Preprocessor to create defined constants for the include file path.
For instance if you have an include file with a relative path such as #include "../../stuff/lib1/thing1.h" you can do something like the following.
#define THING1_H_PATH "../../stuff/lib1/thing1.h"
// ...
#include THING1_H_PATH
The gcc C Preprocessor documentation, The C Preprocessor in section 1.3.2, The #include Directive has this to say:
#include anything else
This variant is called a computed #include. Any `#include' directive
whose argument does not fit the above two forms
is a computed include. The text anything else is checked for macro
calls, which are expanded (see section 1.4 Macros). When this is done,
the result must fit one of the above two variants--in particular, the
expanded text must in the end be surrounded by either quotes or angle
braces.
This feature allows you to define a macro which controls the
file name to be used at a later point in the program. One application
of this is to allow a site-specific configuration file for your
program to specify the names of the system include files to be used.
This can help in porting the program to various operating systems in
which the necessary system header files are found in different places.
How I deal with headers depends in if they are going to be installed (as with a library) or not.
Private headers I would keep in the project source folder:
├── Makefile
└── src
├── header1.cpp
└── header1.h
├── header2.cpp
└── header2.h
└── main.cpp
Then just include them like this:
#include "header1.h"
Public headers (to be installed) I generally put in a project subfolder like this:
├── Makefile
└── src
├── project
│ ├── header1.h
│ └── header2.h
└── header1.cpp
└── header2.cpp
└── main.cpp
And I include them like:
#include <project/header1.h>
In order to locate the public headers you need to set a compiler flag. For GCC that is -I
g++ -Isrc ... etc ...
When the headers are installed they will go somewhere like /usr/include:
── usr
└── include
├── project
│ ├── header1.h
│ └── header2.h
And client software will include them the same way:
#include <project/header1.h>
But they will supply different flag settings to find them:
g++ -I/usr/include ... etc ...
Related
I'm struggling to understand the logic of how includes work in Bazel targets. I want my code to be modular, so I am trying to avoid #include statements with relative or long absolute paths.
Suppose I have the following workspace structure:
tree .
.
├── BUILD
├── is_binary_tree
│ ├── BUILD
│ └── is_binary_tree.cpp
├── lib
│ ├── BUILD
│ ├── graphs.cpp
│ └── graphs.h
└── WORKSPACE
I'm getting the following warning when trying to bazel build //is_binary_tree:is_binary_tree and I don't understand what it means :
WARNING: /is_binary_tree/BUILD:1:10:
in includes attribute of cc_binary rule
//is_binary_tree:is_binary_tree: '../lib' resolves to 'lib' not below
the relative path of its package 'is_binary_tree'. This will be an
error in the future
Why would ../lib resolve to lib. Lib should be in the parent directory of is_binary_tree, so from the standpoint of is_binary_tree it can be found at ../lib, isn't this right?
To get rid of the relative path and avoid having something like #include ../lib/graphs.h in is_binary_tree/is_binary_tree.cpp I added an includes attribute to my is_binary_tree target like so:
is_binary_tree/is_binary_tree.cpp
#include "graphs.h"
int main(){
return 0;
}
is_binary_tree/BUILD
cc_binary(
name="is_binary_tree",
srcs=["is_binary_tree.cpp"],
includes=["../lib"],
deps=["//lib:graphs"],
)
And I'm getting the aforementioned WARNING. What am I missing?
And more broadly, what is the best way to include dependencies without having long relative paths in #include statements ? (I want my code to be modular and not specific to a given Bazel workspace folder organization)
Thanks
That includes should go in //lib:graphs, so that anything which depends on it (has it in deps) uses it. lib/BUILD should look like this:
cc_library(
name = "graphs",
hdrs = ["graphs.h"],
srcs = ["graphs.cpp"],
includes = ["."],
visibility = ["//visibility:public"],
)
Then you drop includes from is_binary_tree and it should work.
In general, each Bazel target contains information about its files. It depends on other targets to use their files.
More broadly, Bazel defaults to #include paths relative to the base of the repository. That means you'd write #include "lib/graphs.h" in any file, whether that's is_binary_tree/is_binary_tree.cpp or x/y/z/foobar.cpp. That avoids collisions between graphics/constants.h and audio/constants.h, without using absolute paths.
I'm trying to compile C++ code into a single binary using .proto files. My current process has 2 steps;
Generate C++ code from 3 .proto files using protoc.
Compile the generated code and my own C++ code into a single .o file.
However, when I try to compile in step 2, the generated code specified outputs as 'com/company/B.pb.h', which fails to be found by the compiler, because the file is in the same directory.
I don't want to manually change the generated code imports as I feel that should be done by protoc, and we also use these proto files for other projects (including generating java code using the same .proto files, which works). Is there a way to specify the generated code's imports WITHOUT changing the proto imports?
EDIT:
Is this an issue with protoc when generating multiple files at once? Should I be using a different command?
I know there are options for java like specifying the package or classname, but I can't find anything similar for C++.
option java_multiple_files = true;
option java_package = "com.company.B";
option java_outer_classname = "B";
Any help is much appreciated. More details below.
Directory structure:
.
├── com
│ └── company # generated code
│ ├── A.pb.cc
│ ├── A.pb.h
│ ├── B.pb.cc
│ ├── B.pb.h
│ ├── C.pb.cc
│ └── C.pb.h
├── Parser.cc
├── Parser.h
└── proto
└── com
└── company
├── A.proto
├── B.proto
└── C.proto
Protoc command: (run from .)
protoc --cpp_out=. --proto_path=proto/ com/company/A.proto com/company/B.proto com/company/C.proto
A.proto snippet:
syntax = "proto3";
option optimize_for = SPEED;
package com.company;
import "com/company/B.proto"; # specified as full path re Google's documentation
...
Parser.cc:
#include "parser.h"
...
Parser.h:
#include "com/company/A.pb.h"
#include "com/company/B.pb.h"
#include "com/company/C.pb.h"
...
G++ command:
g++ -fPIC -Lprotoc -lprotobuf parser.cc -o parser.so
The Error:
fatal error: com/company/B.pb.h: No such file or directory
#include "com/company/B.pb.h"
^~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
I never found a way to specify the output for C++ generated code, but I found a way to compile the code correctly without doing janky workarounds, and I think this is the approach I should have taken at the start. Here goes:
Step 1, the generated C++ code stays the same, and it is generated with path includes, and are compiled in the same directory.
Step 2 becomes a make file (we are using Ruby Make/Rake but the concept is the same)
The makefile specifies;
the parser.cc and all the generated .cc files as the sources.
the $LIBS flags -fPIC -lprotobuf (Note the lack of -Lprotoc here, I ran into errors further along the track. Usually about undefined symbols)
the $INCFLAGS ` -I$(srcdir)/com/company ```. (This is a directory for the make file to include in compilation)
the $VPATH $(srcdir)/com/company. (This is a directory for the make file to search.)
This resulted in a .o file being generated for each .proto file, and a .o file for the parser.cc. Then they are combined into a single .so file which can be used as we intended.
Feel free to ask questions if you run into similar issues.
I'm using sublime text with the sublime linter plugin especially with clang.
When I open a folder, it use the root of the folder as a header location, so if I have
src
├── World
│ ├── Chunk.cpp
│ ├── Chunk.hpp
│ ├── World.cpp
│ └── World.hpp
└── main.cpp
In World.cpp I need to include "World/World.hpp".
But if in World.hpp I include Chunk.hpp the same way ("World/Chunk.hpp"), I get an error but
in World.hpp I have no error. Error are only in file I include that include other file.
I had the same issue. You need to tell clang where to look for the files, i.e. which directories you want to include. Go Preferences --> Package Settings --> SublimeLinter --> Settings and add a new section for clang++:
// SublimeLinter Settings - User
{
"linters":
{
"clang++": {
"I" : [
"${folder}/src",
"${file_path}",
]
}
}
}
In your case the two include directories will actually point to the same path but in general, the first version is to include your source directory (e.g. you have a unit test from a different folder open which accesses code from you src directory) and the second line includes the location of your current file.
If you need different directories, find some more variables you can use here.
I'm building a "framework" library which one I'm trying to integrate Google Tests. It's a pretty small library, that at the end gives me a .so or .dll file.
When I was starting to tests my library, I found a configuration (details below) that works fine on my CMakeFile at my linux environment. But when I try to run the same project using a MSBuild for MSVC14, it gives me a link error
LINK : fatal error LNK1104: cannot open file '..\src\Debug\foobar.lib'
I'm thinking that my cmake is guessing the lib name wrong (foobar.lib instead of foobar.dll), but I couldn't find why nor how to fix it.
Also, I don't know if this is really the best way for me testing this. What I want is a way to test the whole framework (initializing, creating stuffs, checking returns etc..) without a main.cpp file, and meanwhile start to create the unit tests.
So, my question is.. What am I doing wrong that at the Windows environment the linker does not find the foobar lib built by src/CMakeLists.txt? (I checked, and the lib is created in "src/Debug/foobar.dll", same dir that appears at the error, and works fine)
Also, is my method so wrong that windows just don't wanna deal with? lol I mean, it's wrong to do something like I'm trying to do? It's not that I do not want to make unit tests, which I'll be doing soon, but I really like to build and try my lib without using any external exec binary before I starting to do that.
Thanks!
OBS:
My google tests is working fine both in linux and windows;
I can run the test FooA if I remove the FooBar test, which is linking to foobar lib.
Using my linux environment this configuration works perfectly.
Update:
As #vre suggested, I found the macro __declspec(dllexport) and put it before my FooBar class name and the compilation passed, but it crashes when I run and throws this warning when compiling:
warning C4251: 'FooBar::_impl': class 'std::unique_ptr<FooBar::FooBarImpl,
std::default_delete<_Ty>>' needs to have dll-interface to be used by clients of class 'FooBar'
That's because I have a PImp implementation of the FooBar class. So, I have this:
class __declspec(dllexport) FooBar
{
...
private:
class FooBarImpl;
std::unique_ptr<FooBarImpl> _impl;
}
I don't really know what it means yet. Trying to find out why it crashes.
My project has this file tree:
├── CMakeLists.txt
├── include
| ├── FooBar.hpp
├── src
│ ├── CMakeLists.txt
│ ├── FooBar.cpp
│ ├── FooA
│ │ └── CMakeLists.txt
│ ├── FooB
│ │ └── CMakeLists.txt
│ └── FooC
│ └── CMakeLists.txt
└── test
├── CMakeLists.txt
├── FooBar
│ └── FooBarTest.hpp
├── FooA
│ ├── FakeBar.hpp
│ ├── FooATest.hpp
│ └── mockObj.hpp
My main CMakeLists.txt is like this:
...
set(FOOBAR_INCLUDE "${PROJECT_SOURCE_DIR}/include/FooBar.hpp")
# Include src main CMakeLists
add_subdirectory("${PROJECT_SOURCE_DIR}/src")
# Include tests if enabled
if (test)
add_subdirectory("${PROJECT_SOURCE_DIR}/test")
endif ()
My src/CMakeLists.txt:
...
set(FOOBAR_SOURCES "FooBar.cpp")
# Build
add_library(foobar SHARED ${FOOBAR_SOURCES} ${FOOBAR_INCLUDE})
# Links the library with components.
target_link_libraries(foobar FooA FooB FooC)
And my test/CMakeLists.txt is something like this:
enable_testing()
# Include directories used for testing.
include_directories("${CMAKE_SOURCE_DIR}/src"
"${CMAKE_SOURCE_DIR}/include"
"FooA/"
"FooBar/")
# Include the files for testing.
set(INCLUDE_TESTS "${CMAKE_SOURCE_DIR}/src/FooA/FooA.cpp"
"${CMAKE_SOURCE_DIR}/src/FooA/Bar.cpp")
# Include the test source files.
set(TEST_SOURCES "main.cpp"
"FooBar/JepluTest.hpp"
"FooA/FakeBar.hpp"
"FooA/FooATest.hpp")
# Build
add_executable(foobar-test ${TEST_SOURCES} ${INCLUDE_TESTS})
# Links the library with components. (HERE IS WHERE OCCURS THE PROBLEM)
target_link_libraries(foobar-test gtest foobar)
# Not really important right now
add_test(NAME foobar-test COMMAND foobar-test)
Reformulating and enhancing my previous comments:
You need to export symbols from the DLL on Windows otherwise no import library is created, and that's what MSBuild is complaining about.
First you should add to your FooBar.hpp header the following construct:
#ifdef WIN32
#ifdef FOOBARLIB_EXPORTS
#define FOOBARLIB_API __declspec(dllexport)
#else
#define FOOBARLIB_API __declspec(dllimport)
#endif
#else
#define FOOBARLIB_API
#endif
Later mark your classes, functions and symbols to be exported as follows:
void FOOBARLIB_API foobar(char*)
{
}
In your CMakeLists.txt after creating the shared library target foobar add the line:
target_compile_definitions(foobar PRIVATE FOOBARLIB_EXPORTS)
EDIT:
As #vre commented, these CMake properties are also needed because Windows does not load a DLL located in another folder, causing a crash when it tries to run the executable. So, when a DLL is build and the CMAKE_RUNTIME_OUTPUT_DIRECTORY variable is set, the output library goes to the same directory as the test .exe file.
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
What's a good directory structure for larger C++ projects using Makefile ?
This is how my directory structure looks at the moment:
lib/ (class implementations *.cpp)
include/ (class definitions *.h)
tests/ (main.cpp for quick tests)
Now, I'm not sure how my Makefile should look like... it doesn't seem to work when .cpp files and .h files aren't in the same directory. Could anyone point me to a common directory structure with an accompanying Makefile so that I don't reinvent the wheel ?
Separating the .cpp of the .h file is not always a good solution. Generally I separate both of them when it is used as a library (public header in include and private header with the source code).
If it is a library, this structure is ok.
lib/ (class implementations *.cpp .h)
include/ (class definitions *.h) <- Only those to be installed in your system
tests/ (main.cpp for quick tests)
doc/ (doxygen or any kind of documentation)
If it is a application
src/ (source for the application)
lib/ (source for the application library *.cpp *.hpp)
include/ (interface for the library *.h)
tests/ (main.cpp for quick tests) <- use cppunit for this part
doc/ (doxygen or any kind of documentation)
Use the flag -I$(PROJECT_BASE)/include to specify the include path for the compilation
If it is a big project, it can be good to use tool like autoconf/automake or cmake to build everything. It will ease the development.
For those who find this question after 2020, an alternative modern and reasoned vision of "Canonical Project Structure" for C++ has been presented by Boris Kolpackov: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1204r0.html
Briefly - no include/ and src/ split. All headers, sources, modules and unit tests go into one directory. Implementation details may be separated from public API by moving to <name>/<name>/details/ subdirectory.
<name>/
├── <name>/
│ ├── headers...
│ ├── sources...
│ ├── modules...
│ └── unit tests...
└── tests/
├── functional_test1/
├── functional_test2/
├── integration_test1/
├── integration_test2/
└── ...
For example:
bestlib/
├── bestlib/
│ ├── foo.h
│ ├── foo.cpp
│ ├── foo.test.cpp
│ ├── bar.h
│ ├── bar.cpp
│ └── bar.test.cpp
└── tests/
├── functional_test1/
└── integration_test1/
If you have many source files, it may also be a good idea to further subdivide your source directory. For instance, one subdirectory for the core functionality of your application, one for the GUI, etc.
src/core
src/database
src/effects
src/gui
...
Doing so also forces you to avoid unneeded relationships between your "modules", which is a prerequisite to nice and reusable code.
There is no one specific or required directory structure.
You can set it up anyway you like. Your problem is simple to solve. Just instruct Makefile to look into subdirectories or put compiled objects into subdirectories instead of using just current directory.
You would just use in Makefile paths:
%.o : %.cpp
replace with
bin/%.o : %.cpp
So it will check if binary file in directory bin exists and so on, you can apply the same to locations where files are compiled.
There are ways to add/remove/modify paths of source and object files.
Have a look at gnu make manual, specifically section 8.3 Functions for File Names,and the one before that 8.2 Functions for String Substitution and Analysis.
You can do stuff like:
get a list of objects from list of source files in current directory:
OBJ = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
Output:
Application.o Market.o ordermatch.o
If binary objects are in subdirectory bin but source code is in current directory you can apply prefix bin to generated object files:
OBJ = $(addprefix bin/,$(patsubst %.cpp, %.o, $(wildcard *.cpp)))
Output:
bin/Application.o bin/Market.o bin/ordermatch.o
And so on.
This is an old question. But you can consider the Pitchfork Project as a general guide.
https://github.com/vector-of-bool/pitchfork for the project.
Some Documentation here
There is no "good directory structure". Pick a structure you're comfortable with and stick to it. Some like placing source files (headers and implementation files) in a src/ directory, so the root directory of the project has nothing but a makefile, a readme and little else. Some like placing helper libraries under a lib/ directory, unittests under test/ or src/test/, documentation under doc/ etc.
I have yet to hear of anyone splitting header files and implementation files into two distinct directories though. Personally I don't like splitting files into directories much. I usually place all my source in a single directory and all the documentation in another directory. If I rely on good search tools anyway, there's no need for a complex directory structure.
make can deal with the sort of structure where the makefile resides in a different directory than the source. The only thing is that it will invoke the rules from the directory of the makefile -- compilers usually have no problem compiling source that is in some subdirectory. You don't have to specify relative paths in your #includes; just specify the include path with compiler flags (gcc's -I flag etc).
If you haven't seen it before read Recursive Make Considered Harmful.
Short, short version: Though very common the recursive make idiom is less than optimal and gets ever worse as projects grow larger and more complicated. An alternative is presented.
Related link: What is your experience with non-recursive make?