dynamic include a CUDA file - c++

I have two solvers for an application, one in C and other in CUDA. The Makefile detects if nvcc is available and automatically switches to use the CUDA solver. Otherwise, it should use the C solver.
I wanted to include the header of the CUDA solver only if nvcc is detected, so I did this in the main.cpp file:
#if (NVCC_TEST == nvcc)
#include "utilCUDA.h"
#endif
NVCC_TEST is declared in the Makefile like this:
NVCC_RESULT := $(shell which nvcc 2> NULL)
NVCC_TEST := $(notdir $(NVCC_RESULT))
The problem is that the main file includes utilCUDA.h even when nvcc is not available in the system. Any ideas?

Variables defined in the make environment don't automatically show up at the source code level when compiling. Referring to this question/answer, in the section of your Makefile where you set make variables for CUDA vs. non-CUDA usage, do the following:
NVCC_RESULT := $(shell which nvcc 2> NULL)
NVCC_TEST := $(notdir $(NVCC_RESULT))
ifeq ($(NVCC_TEST),nvcc)
CC := nvcc
CCFLAGS := -DUSE_CUDA
else
CC := g++
CCFLAGS := -DNO_CUDA
endif
Then whereever in your Makefile you are specifying the compile command, add the $(CCFLAGS) to the compile command line. Any source code compiled in that command line will see that define.
Then in your source code, you can do:
#ifdef USE_CUDA
#include "utilCUDA.h"
#endif
#ifdef NO_CUDA
// whatever else you want to do.
#endif
By the way, if you attempt to compile a .cpp file with nvcc, you're probably not going to get the results you expect. If you need to do this, use the nvcc -x cu option when you specify your compile command.

Related

Trying to compile simple project that uses TRI DDS using cygwin gcc

I am trying to take the TRI DDS example code. It is all setup to build with MSVS2012 and comes with MSVS2012 proj/solution files.
However I want to try to build this using Cygwin and g++/gcc. I have got so far and then hit issues.
My cpp/h files are taken from their example - the user code is basic c++ but the generated files / RTI DDS files I think are causing an issue.
The basic source files are:
Hello.cpp
HelloPublisher.cpp/h
HelloSubscriber.cpp/h
HelloWorld.idl
RTI-DDS generator uses HelloWorld.idl to generate further files (.cxx/h files). I am not expecting to change any of the RTI-DDS files and the code within the 4 source files are fairly vanilla, so I can compile them if I hack out all the calls to RTI-DDS.
The area I want to focus on is the makefile / environment. Here are the pertinent parts of my makefile (note the linker parts are not complete because I have not got that far yet - the compile still fails):
note NDDSHOME = c:\Program Files\rti_connext_dds-5.3.0 as an env var.
# Setup minimal "un-polluted" paths to try to avoid any conflicts
makePaths=/usr/local/bin:/usr/bin:$(NDDSHOME)/bin
export PATH := $(makePaths)
#Include Paths
INCLUDES = -I. -I"$(NDDSHOME)/include" -I"$(NDDSHOME)/include/ndds" -I"$(NDDSHOME)/include/ndds/hpp"
#Compiler / options:
DEFINES = -DRTI_WIN32 -DRTI_STATIC -DWIN32 -D_WIN32_WINNT=_WIN32_WINNT_WIN7
CC = g++
CC_FLAGS = -std=c++11 -Wall -Wextra -lWS2_32
EXEC = run
# C++ files
SOURCES = $(wildcard *.cpp)
OBJECTS = $(SOURCES.cpp=.o)
# Main Target
$(EXEC): $(OBJECTS)
# Don't do linking yet - compile not working!
%.o: %.cpp
$(CC) $< -o $# -c $(DEFINES) $(CC_FLAGS) $(INCLUDES)
I know the INCLUDES paths are working because I get different errors when they are not (can't find...)
But the error I get at the moment is:
/usr/include/w32api/winsock2.h:1004:68: error: conflicting declaration of c function 'int gethostname(char*, int)'
:
:
/usr/include/sys/unistd.h:268:6 note: previous declration 'int gethostname(char *, size_t)'
note I have to copy this by hand from my other PC... so I have abbreviated the complete message.
I thought I was close to solving this by looking at other questions with similar errors, but I can't quite make the connection to fix this. I have tried adding other defines to specify the windows version, but that did not fix it. I know there is a linker option that we need to use for things like mingw that is what the -lws2_32 flag is set for - but I have not got to the linker stage yet :(
I guess either the unistd.h or the winsock2.h should not really both be included, but I can't quite figure out what define (or other) I need to add...
Any ideas?

How do I choose what source files get compiled for each platform?

Say I have a file structure like:
win32/ Something.cpp
linux/ Something.cpp
Something.h
main.cpp
How would I be able to implement:
UNAME = $(shell uname -s)
ifeq ($(UNAME), Linux)
OS = linux
else
OS = win32
endif
all:
g++ ?????
I've been at a loss for around an hour now. I've never attempted cross platform makefiles so I usually just let the IDE handle it but now I need to create it because the IDE isn't really cut out for cross platform projects.
PS: Something.h is just a class definition/prototype and the linux/ and win32/ source files are just providing a method for that class. Problem is that I get a compilation error saying the class is already declared if both exist without some form of build target or whatever.
Thanks.
Multi platform Makefiles are an advanced topic. You might want to take a look at scons. Anyway, here is how you could make your case work:
Build your list of sources depending on the $(UNAME):
UNAME = $(shell uname -s)
TARGET = myprogam
SRC_COMMON = main.cpp
ifeq ($(UNAME), Linux)
SRC_OS = $(wildcard linux/*.cpp)
else
SRC_OS = $(wildcard win32/*.cpp)
endif
SRC = $(SRC_COMMON) $(SRC_OS)
OBJ = $(SRC:.cpp=.o)
$(TARGET): $(OBJ)

Linking pcap library in OpenWrt Makefile

My simple pcap test app compiles and runs fine using: gcc main.c -o test -lpcap
but when using the OpenWrt SDK: make package/myapp/compile V=s
I get the error message:
main.c:(.text.startup+0x24): undefined reference to `pcap_lookupdev'
collect2: error: ld returned 1 exit status
From what I've read, I need to add the line:
LDFLAGS = -lpcap
to one of the Makefiles, but I'm not sure where it should go. What confuses me is that I can use the pcap constant PCAP_ERRBUF_SIZE, can anyone tell me why I can access this, but not pcap functions?
main.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <pcap.h>
int main(int argc, char **argv)
{
printf("Hello PCAP!\n");
char *dev, errbuf[PCAP_ERRBUF_SIZE];
printf("%d\n\n", PCAP_ERRBUF_SIZE);
// Make works without this part
dev = pcap_lookupdev(errbuf);
printf("Device: %s\n", dev);
return 0;
}
Makefile
include $(TOPDIR)/rules.mk
PKG_NAME:=myapp
PKG_VERSION:=0.1
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/myapp
SECTION:=utils
CATEGORY:=Utilities
DEPENDS:=+libpcap
TITLE:=Intro to PCAP for OpenWrt
endef
define Package/myapp/description
Outputs device name
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
LDFLAGS=-lpcap
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Package/myapp/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/myapp $(1)/usr/bin/
$(INSTALL_DIR) $(1)/etc/init.d/
$(INSTALL_BIN) files/myapp.init $(1)/etc/init.d/myapp
$(INSTALL_DIR) $(1)/etc/config
$(INSTALL_CONF) files/myapp.config $(1)/etc/config/myapp
endef
$(eval $(call BuildPackage,myapp))
Constants and the like used in code are resolved during compilation and come from header files. So the pcap.h header file is found (apparently by default).
I would have expected DEPENDS:=+libpcap to handle the linking for you (I'm not sure why else it would be necessary, but ). (Is that the correct format for that line?)
You actually want LDLIBS not LDFLAGS for this (assuming you are using the built-in rules and variables). See 10.3 Implicit Variables for what they each mean.
Without knowing what the rest of that make framework is doing though I can't say whether either LDLIBS or LDFLAGS will actually work though. That framework might have its own variable for this.
I figured out how to compile native C code for OpenWrt (runnin on a mips processor inside of a TP-LINK router) that depends on other libs (also in C) and generate .ipk s for both (the library and the executable) via a single makecommand. The library itself needed to be fetched from
I documented the efforts on my blog here
Basically there are three Makefiles involved - one for the library which tells the build system where to get the tarball from. The other two would be for your native C code. Consider my case for example: I want compile my code (mfm383c) that makes uses of a library (libmodbus):
/package/libmodbus/Makefile - this specifies URL from where to get the tar ball of the sources and the system will fetch the sources and compile it for you. It also tells the system where to place the .so file when the .ipk is installed on the OpenWrt target
/package/mfm383c/src/Makefile - this Makefile take care of telling the build system how to compile the .c and .h and also passes the dependency flag to the linker (-lmodbus)
/package/mfm383c/Makefile - This Makefile is the most important of the three - it tells the build system to build the libmodbus library before building mfm383c to ensure that the dependencies are met. We also need to make sure that the modbus.h file included in mfm383c.c can be found in the right place. The most notable section of this file being the following line at the end:
$(eval $(call BuildPackage,mfm383c,+libmodbus))
and the part about the code being dependent on another package in the define section:
DEPENDS:=+libmodbus
All three makefile are posted on my blog - they were too big to post here

native-activity sample project won't compile if I change file exteension to .cpp

I've compiled the native activity sample and it runs fine. When I switch from main.c to main.cpp I get a compiler error
$ /cygdrive/c/android-ndk-r7/ndk-build
make: *** No rule to make target `jni/main.c', needed by `obj/local/armeabi/objs/native-activity/main.o'. Stop.
I changed the make file to main.cpp.
I'm new to Android and Linux. I'm using Cygwin.
I had to delete the object files. Dumb mistake.
Check your Android.mk file looking for main.c and change it to main.cpp
LOCAL_SRC_FILES := main.c
must be:
LOCAL_SRC_FILES := main.cpp

Testing C++ program with Testing classes over normally used classes

This will probably be a bot of a waffly question but ill try my best.
I have a simple c++ program that i need to build testing for. I have 2 Classes i use besides the one i actually am using, these are called WebServer and BusinessLogicLayer.
To test my own code i have made my own versions of these classes that feed dummy data to my class to test it functionality.
I need to know a way of somehow, via a makefile for instance, how to tell the source code to use the test classes over the normally used classes. The test classes are in a different "tester" c++ file, and the tester c++ file also has its own header file.
Regards
Paul
P.S. This is probably a badly worded question, but i dont know any better way to put my question.
You can define abstract base classes that declare the public interfaces for your components, then wire the objects together at runtime (in main() or something else fairly high up in the food chain). In testing, you simply wire up different objects.
To build debug and release versions of a program with source code in directories ${SRC_DIR_1} and ${SRC_DIR_2}:
CXX := g++
CPPFLAGS = ...
CXXFLAGS = ...
SRC_DIR_1 := ...
SRC_DIR_2 := ...
ifeq (${debug},1)
BIN_DIR := ./obj_debug
CXXFLAGS += -g
else
BIN_DIR := ./obj_release
CXXFLAGS += -DNDEBUG
endif
# Make sure that the directory exists.
TEMP := ${shell test -d ${BIN_DIR} || mkdir ${BIN_DIR}}
# Tell make to search each directory
VPATH := ${SRC_DIR_1}:${SRC_DIR_2}
# You can modify this to use a suffix other than .cc
${BIN_DIR}/%.o : %.cc
${CXX} ${CPPFLAGS} ${CXXFLAGS} -c $< -o $#
# Build the requested version of the program.
ifeq (${debug},1)
default: program_name_debug
else
default: program_name
endif
tidy::
#${RM} -r ./obj_*
In the Project Configuration dialog, specify the target name as "program_name, program_name_debug". (Replace program_name with the name of your program.)
To build the program, invoke "make debug=X" with X replaced by either 0 or 1.
Reference
Why does your tester code have a header file of its own? Your test code should have the same interface as the code it emulates, and using the same header file prevents a lot of headaches.
Anyway, this will work:
real_program: WebServer.o BusinessLogicLayer.o
test_program: tester.o
real_program test_program: MyClass.o OtherThings.o
$(LINK) $^ -o $#