I'm trying to compile a CUDA application with Nsight that compiles .cpp files to .o files then links the main application. I'm basing my build off the NVIDIA "Parallel for All" example Separate Compilation and Linking of CUDA C++ Device Code and its Makefile:
objects = main.o particle.o v3.o
all: $(objects)
nvcc -arch=sm_20 $(objects) -o app
%.o: %.cpp
nvcc -x cu -arch=sm_20 -I. -dc $< -o $#
clean:
rm -f *.o app
When I copy my code into a new directory and use that Makefile (adapted to my filenames and other flags, of course), everything works fine.
But I can't figure out how to get the same options into Eclipse and as such the build always fails with the following errors:
/usr/local/cuda-7.5/bin/nvcc -G -g -O0 -std=c++11 -gencode arch=compute_50,code=sm_50 -odir "src" -M -o "src/Object.d" "../src/Object.cpp"
/usr/local/cuda-7.5/bin/nvcc -G -g -O0 -std=c++11 --compile -x c++ -o "src/Object.o" "../src/Object.cpp"
../src/kernels.cu:31:12: error: ‘blockIdx’ was not declared in this scope
#... lots more "no one told me this was CUDA" errors
../src/Object.cpp:125:26: error: expected primary-expression before ‘<’ token
#... can't call CUDA kernels from cpp either ...
My project files' relevant includes are are:
Object.cpp:
#include "Object.h"
#include "kernels.cu"
main.cpp: (same error with fname as main.cu)
#include "Object.h"
kernels.cu:
#include "Object.h"
Object.h:
#include <cuda_runtime.h>
The code compiles fine with the custom makefile. The missing piece appears to be the -dc (device code) flag but I don't know how to enable it in Nsight Eclipse edition. I know I can create a Makefile project, but I'd really prefer to do it from within Eclipse so that all the introspection works right etc.
I solved the problem, though I still don't entirely understand it...
It seems that the -x c++ was the key flag, not -dc.
The default build settings of Nsight Eclipse work correctly when the files are renamed as follows:
Object.cpp Object.cu:
#include "Object.h"
#include "kernels.cuh"
main.cpp: (main.cu is also good)
#include "Object.h"
kernels.cu kernels.cuh:
#include "Object.h"
Object.h:
#include <cuda_runtime.h>
Apparently .cu files are compiled to .o files with -x cu (language CUDA) and then linked but .cpp files are compiled with language -x c++ and therefore do not see all of the CUDA markup. The main.cpp file has no actual CUDA in it so it doesn't matter.
Without renaming the kernels.cu to kernels.cuh build fails with multiple definition errors because it's compiled twice.
The current configuration appears to work, I hope this is helpful to someone. I really wish there was some clear documentation or settings on how file extensions affect build rules in Nsight...
Related
So, I was following a simple C++ with SDL tutorial for linux but i encounter some errors on my way.
First of all I'm using Geany and i downloaded the corresponding SDL2 libs, here is the thing:
in my project folder there is a main.cxx file, which i open with geany as i mentioned before:
I included this libraries:
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
First i encountered a pelculiar error, compilation performs sucessfully but when it comes to build i got this error:
main.cxx: undefined reference to `SDL_Init'
After searching a bit i found out that i had to add the tag -lSDL to my geany build options so they would end up being somethinf like this:
Compile:
g++ -Wall -c -lSDL "%f"
Build:
g++ -Wall -o -lSDL "%e" "%f"
But there is a problem, now when I execute the build command i get a:
G ++: error: main: There is no such file or directory
Why am i getting this error, am I including a wrong library or g++ has problems with .cxx files?
I already tried converting between .cxx and .cpp.
Thanks in advance.
g++ -Wall -c -lSDL2 "%f"
There is absolutely no need to specify libraries during compilation phase. Remove -lSDL.
g++ -Wall -o -lSDL2 "%e" "%f"
It invokes compiler, implies linking (no -c or other operation-specific flags), and sets output file name to -lSDL2. That is, linker will output resulting binary in a file named -lSDL2 in current working directory. Then, when it comes what files to link, it goes main, which supposed to be -o main, but since you've broken flags order it is now just ordinary file name that linker will try to link into resulting binary. It so happens that this file doesn't exist.
Long story short, make correct linking line - g++ -o "%e" %f -lSDL2 (libraries comes last, library order is also important).
I'm trying to modify and compile uvccapture on the Raspberry Pi. I got the source from here (it's just a few files).
(I think) the only external files it needs are those of jpeglib which I downloaded from here.
When compiling, where do I put the jpeglib source files? UVCCapture has the following line:
#include <jpeglib.h>
Does that mean I should put the jpeglib source files in the same directory as the UVCCapture source files? That seems messy. How can I set up the compiler (modify the Makefile?), and where should I put the jpeglib files so that I don't need to change the uvccapture include file lines?
And a side question, how come it only includes the .h file and not the .c file? (I'm pretty new to C/C++)
Here is the Makefile:
CC=gcc
CPP=g++
APP_BINARY=uvccapture
VERSION = 0.4
PREFIX=/usr/local/bin
WARNINGS = -Wall
CFLAGS = -std=gnu99 -O2 -DLINUX -DVERSION=\"$(VERSION)\" $(WARNINGS)
CPPFLAGS = $(CFLAGS)
OBJECTS= uvccapture.o v4l2uvc.o
all: uvccapture
clean:
#echo "Cleaning up directory."
rm -f *.a *.o $(APP_BINARY) core *~ log errlog
install:
install $(APP_BINARY) $(PREFIX)
# Applications:
uvccapture: $(OBJECTS)
$(CC) $(OBJECTS) $(XPM_LIB) $(MATH_LIB) -ljpeg -o $(APP_BINARY)
Thanks
The source file (uvccapture.c) doesn't care where the header file (jpeglib.h) is -- at least it shouldn't. The compiler must be told where to look for header files; traditionally, the header files go in some directory like inc_files/, and the compiler is invoked with a command like
gcc -blah -blah -blah -Iinc_files -c -o uvccapture.o uvccapture.c
If you use Make, then Make should execute a command like that. So either edit the makefile, or put the header files in the current directory.
The sane way to use #include in C/C++ is to have source files and header files include header files. That is, in foo.c there will be a couple of lines like:
#include <bar>
#include "baz.h"
and in baz.h there might be a few lines like:
#include <vector>
#include "qux.h"
You almost never see #include foo.c, because it's almost never a good idea.
I have a header in my project, called Core.h, that I use as a pre-compiled header:
$(CXX) $(CXX_CFLAGS) -x c++-header Core.h
Which creates a file named Core.h.gch
*#include "Core.h" is the first directive of every source file in the module.
On OS X, it works fine -- my project compiles fine & it compiles pretty fast.
On Linux however, 7 of my 100+ files give the following warning:
warning: Core.h.gch: too short to be a PCH file
Just like every other source file, #include "Core.h" is the first line of these files.
Has anyone ever come across this? Possible causes? Why would it only be a few files that include the PCH that would give the warning ?
I use gcc version 4.1.2 on Linux, 4.2.1 on OSX
Thanks!
EDIT:
Here is basically how I build the library:
.PHONY: all
all: $(MY_PCH) MYLIB.so MYLIB.a
MYLIB.so: $(MY_PCH) $(MY_OBJECTS)
$(CXX) $(MY_OBJECTS) $(CXX_LDFLAGS) -o $#
MYLIB.a: $(MY_PCH) $(MY_OBJECTS)
$(AR) $(ARFLAGS) $# $(MY_OBJECTS)
$(MY_PCH):
$(CXX) $(CXX_CFLAGS) -x c++-header Core.h
Are you using a parallel make? Possibly g++ is trying to read the .gch file while another instance is writing to it.
I think this is a question about automake.
http://home.gna.org/cal3d/
I'm struggling with the cally demo of Cal3D.
The first problem I ran into was that the Cal3D code base is missing #include <cstring> and #include <memory> in a lot of places.
Doing this every time I got an error in any source file in Cal3d was enough to let me compile it.
The cally demo also needed some #include <cstring>
Now my problem is that HAVE_SDL_H is not defined when tick.cpp is compiled.
The configure and makefile seems to accept that SDL is installed on my system, but the macros in src/tick.cpp doesn't.
I guess there is some kind of bug in the configure.in or something, but I don't seem to find out just what it is.
if g++ -DHAVE_CONFIG_H -I. -I. -I.. -O3 -ffast-math -funroll-all-loops -g -O2 -I/usr/include -I/usr/local/include -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT -MT tick.o -MD -MP -MF ".deps/tick.Tpo" -c -o tick.o tick.cpp; \
then mv -f ".deps/tick.Tpo" ".deps/tick.Po"; else rm -f ".deps/tick.Tpo"; exit 1; fi
tick.cpp:144:5: error: #error "no timer implemented for your plateform"
Edit:
I've finally compiled the demo.
When I compiled cal3d I added #include <cstring> to the following files:
src/cal3d/hardwaremodel.cpp
src/cal3d/platform.cpp
src/cal3d/renderer.cpp
src/cal3d/submesh.cpp
src/cal3d_converter.cpp
When I compiled cally I added #include <cstring> to the following files:
src/demo.cpp
src/model.cpp
In model.cpp I changed line 640 from
glBindTexture(GL_TEXTURE_2D, (GLuint)pCalRenderer->getMapUserData(0));
to
glBindTexture(GL_TEXTURE_2D, *(GLuint*)pCalRenderer->getMapUserData(0));
I also did some uglier changes to get src/tick.cpp to compile.
In src/tick.cpp I removed everything that had anything to do with SDL. I also removed a macro if clause checking for __i386__ or __ia64__, so that Tick::getTime() could also be compiled.
I know that this is not a proper fix, so improvements are very much welcome.
64-bit OpenSuSE with a 2.6.27 kernel.
GCC: 4.3.2
GNU Automake: 1.10.1
GNU Autoconf 2.63
64-bit versions of the SDL library is installed with zypper (through the GUI).
Solution
In configure.in change
AC_CHECK_HEADERS([SDL.h])
to
AC_CHECK_HEADERS([SDL/SDL.h])
(then run autoreconf and ./configure)
in tick.cpp change all checks for HAVE_SDL_H to HAVE_SDL_SDL_H
This is all due to a restructuring in the sdl library.
The errors you got with missing #include <cstring> and #include <memory> is mainly du to a cleanup that happened in GNU headers: inclusion of unnecessary headers were removed and consequently programs not including the proper headers for the features they use face compiling errors.
About HAVE_SDL_H, most likely, your Linux distribution is missing packages.
You probably need to install the SDL library. Some Linux distributions like Ubuntu split the packages between the library runtime and the dev files so you need to install both packages
sudo apt-get install libsdl1.2-dev
Regarding:
if g++ -DHAVE_CONFIG_H -I. -I. -I.. -O3 -ffast-math -funroll-all-loops -g -O2 -I/usr/include -I/usr/local/include -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT -MT tick.o -MD -MP -MF ".deps/tick.Tpo" -c -o tick.o tick.cpp; \
then mv -f ".deps/tick.Tpo" ".deps/tick.Po"; else rm -f ".deps/tick.Tpo"; exit 1; fi
tick.cpp:144:5: error: #error "no timer implemented for your plateform"
It indeed fails to compile because HAVE_SDL_H is not defined in config.h. When you look at configure.in you see it's using AC_CHECK_HEADERS([SDL.h])
From the autoconf manual:
— Macro: AC_CHECK_HEADERS (header-file..., [action-if-found], [action-if-not-found], [includes])
For each given system header file header-file in the blank-separated argument list that exists, define HAVE_header-file (in all capitals). If action-if-found is given, it is additional shell code to execute when one of the header files is found. You can give it a value of ‘break’ to break out of the loop on the first match. If action-if-not-found is given, it is executed when one of the header files is not found.
So, AC_CHECK_HEADERS([SDL.h]) makes configure search for SDL.h in /usr/include and doesn't find it because its (new?) path is /usr/include/SDL/SDL.h
As a workaround, use CPPFLAGS to add system header search paths when invoking configure:
./configure CPPFLAGS="-I/usr/include/SDL"
Now you may want to fix configure.in
configure.in uses AM_PATH_SDL(1.2.0) which will end up invoking sdl-config --cflags to define SDL_CFLAGS. (the implementation of AM_PATH_SDL typically lies in the /usr/share/aclocal/sdl.m4 file)
# Check for SDL
AM_PATH_SDL(1.2.0)
LDFLAGS="$LDFLAGS $SDL_LIBS"
CXXFLAGS="$CXXFLAGS $SDL_CFLAGS"
AC_CHECK_HEADERS([SDL.h])
AC_LANG_CPLUSPLUS
sdl-config --cflags returns -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT but those -I and -D directives should not end up in CFLAGS anyway but rather in CPPFLAGS (as per the autoconf manual). Hence I would say there is already something wrong "at the SDL level".
Now take a look at the AC_LANG documentation:
‘C’
Do compilation tests using CC and CPP and use extension .c for test programs. Use compilation flags: CPPFLAGS with CPP, and both CPPFLAGS and CFLAGS with CC.
‘C++’
Do compilation tests using CXX and CXXCPP and use extension .C for test programs. Use compilation flags: CPPFLAGS with CXXCPP, and both CPPFLAGS and CXXFLAGS with CXX.
Moving the AC_LANG_CPLUSPLUS up so that it at least above AC_CHECK_HEADERS([SDL.h]) should make it now use g++ and CXXFLAGS when trying to compile SDL.h which should success since SDL_CFLAGS were added to CXXFLAGS. (again, it should really be SDL_CPPFLAGS but you won't change SDL...)
How can I get precompiled headers working with GCC?
I have had no luck in my attempts and I haven't seen many good examples for how to set it up. I've tried on Cygwin GCC 3.4.4 and using 4.0 on Ubuntu.
I have definitely had success. First, I used the following code:
#include <boost/xpressive/xpressive.hpp>
#include <iostream>
using namespace std;
using namespace boost::xpressive;
// A simple regular expression test
int main()
{
std::string hello("Hello, World!");
sregex rex = sregex::compile( "(\\w+) (\\w+)!" );
smatch what;
if( regex_match( hello, what, rex ) )
{
std::cout << what[0] << '\n'; // Whole match
std::cout << what[1] << '\n'; // First capture
std::cout << what[2] << '\n'; // Second capture
}
return 0;
}
This was just a Hello, World! program from Boost Xpressive. First, I compiled with the -H option in GCC. It showed an enormous list of headers that it used. Then, I took a look at the compile flags my IDE (Code::Blocks) was producing and saw something like this:
g++ -Wall -fexceptions -g -c main.cpp -o obj/Debug/main.o
So I wrote a command to compile the Xpressive.hpp file with the exact same flags:
sudo g++ -Wall -fexceptions -g /usr/local/include/boost/xpressive/xpressive.hpp
I compiled the original code again with the -H and got this output:
g++ -Wall -fexceptions -H -g -c main.cpp -o obj/Debug/main.o
! /usr/local/include/boost/xpressive/xpressive.hpp.gch
main.cpp
. /usr/include/c++/4.4/iostream
.. /usr/include/c++/4.4/x86_64-linux-gnu/bits/c++config.h
.. /usr/include/c++/4.4/ostream
.. /usr/include/c++/4.4/istream
main.cpp
The ! means that the compiler was able to use the precompiled header. An x means it was not able to use it. Using the appropriate compiler flags is crucial. I took off the -H and ran some speed tests. The precompiled header had an improvement from 14 seconds to 11 seconds. Not bad, but not great.
Note: Here's the example. I couldn't get it to work in the post.
BTW: I'm using the following g++:
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Firstly, see the documentation here.
You compile headers just like any other file but you put the output inside a file with a suffix of .gch.
So for example if you precompile stdafx.h you will have a precompiled header that will be automatically searched for called stdafx.h.gch anytime you include stdafx.h
Example:
stdafx.h:
#include <string>
#include <stdio.h>
a.cpp:
#include "stdafx.h"
int main(int argc, char**argv)
{
std::string s = "Hi";
return 0;
}
Then compile as:
> g++ -c stdafx.h -o stdafx.h.gch
> g++ a.cpp
> ./a.out
Your compilation will work even if you remove stdafx.h after step 1.
The -x specifier for C++ precompiled headers is -x c++-header, not -x c++. Example usage of PCH follows.
pch.h:
// Put your common include files here: Boost, STL as well as your project's headers.
main.cpp:
#include "pch.h"
// Use the PCH here.
Generate the PCH like this:
$ g++ -x c++-header -o pch.h.gch -c pch.h
The pch.h.gch must be in the same directory as the pch.h in order to be used, so make sure that you execute the above command from the directory where pch.h is.
Call GCC the same way as if you call it for your source file, but with a header file.
E.g.,
g++ $(CPPFLAGS) test.h
This generates a file called test.h.gch.
Every time GCC searches for test.h, it looks first for test.h.gch and if it finds it it uses it automatically.
More information can be found under GCC Precompiled Headers.
I have managed to get precompiled headers working under gcc once in the past, and I recall having problems then as well. The thing to remember is that gcc will ignore the file (header.h.gch or similar) if certain conditions are not met, a list of which can be found on the gcc precompiled header documentation page.
Generally it's safest to have your build system compile the .gch file as a first step, with the same command line options and executable as the rest of your source. This ensures the file is up to date and that there are no subtle differences.
It's probably also a good idea to get it working with a contrived example first, just to remove the possibility that your problems are specific to source code in your project.
Make sure to -include your_header.h
This is how I precompiled and used bits/stdc++.h collection.
Code
#include <bits/stdc++.h>
Then I located the lib by compiling my file with -H and looking at output
g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable
where I saw
. /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h
So I made a new directory bits inside of current one and copied stdc++.h from there.
Then I ran
g++ bits/stdc++.h -O3 -std=c++14 -pthread
which generated bits/stdc++.gch
Normally I compiled my code via
g++ sol.cpp -O3 -pthread -lm -std=c++14 -o executable
, but I had to modify that to
g++ sol.cpp -include bits/stdc++.h -O3 -pthread -lm -std=c++14 -o executable
as it only resolved to .gch file instead of .h with -include bits/stdc++.h
That was key for me. Other thing to keep in mind is that you have to compile *.h header file with almost the same parameters as you compile your *.cpp. When I didn't include -O3 or -pthread it ignored the *.gch precompiled header.
To check if everything's correct you can measure time difference via comparing result of
time g++ sol.cpp ...
or run
g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable
again and look for header paths and if you now get ! before library path, for example
! ./bits/stdc++.h.gch
....
A subtle tip about the file extension that tripped me up, because I wasn't paying close enough attention: the .gch extension is added to the precompiled file's full name; it doesn't replace .h. If you get it wrong, the compiler won't find it and silently does not work.
precomp.h => precomp.h.gch
Not:
precomp.h => precomp.gch
Use GCC's -H to check if it's finding/using it.