I'm trying to compile a multi file bit of code which up until now has been working fine.
But now I am getting some linker errors. I have a class definition 'njPhaseSpace' which is reported as being:
ld: duplicate symbol njPhaseSpace::njPhaseSpace(int)in Source/Currents.o and
/var/folders/p8/0bwv51kn2w5cx4jnsg6xm7340000gn/T//ccb0Psoz.o for architecture x86_64
I have no idea what the /var/folder/.../ccb0Psoz.o file is about and it isnt (intentionally) begin used in my project.
if I change the name to something different - but similar - such as njPhaseSpaceX it will compile and link up fine. But then I clean the project using 'make clean' and when I try to remake I get the same link error again! (but with a different /var/.../XXXXXX.o file)
Any suggestions?
Cheers
UPDATE: More strange things: When I look in the /var/folder/... directory to see which file is causing the duplication no such file exists!
UPDATE: The njPhaseSpace source file is:
// Standard header files
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <stdio.h>
#include <math.h>
#include <complex>
#include <iomanip>
#include "LoadBar.h"
// CLHEP header files
#include <CLHEP/Vector/LorentzVector.h>
#include <CLHEP/Random/RanluxEngine.h>
// More convenient label for four-vectors
typedef CLHEP::HepLorentzVector HLV;
// Definition of structure to hold the phase-space point
struct ParticleStruct {
HLV pa;
HLV pb;
HLV pep;
HLV pem;
HLV p1;
HLV p2;
HLV p3;
double xa;
double xb;
} ;
// A class for the n-jet phase space
class njPhaseSpace {
private:
// Incoming Particle Momenta
HLV pa;
HLV pb;
// Emitted leptons
HLV pep;
HLV pem;
// Outgoing parton momenta
std::vector <HLV> OutgoingPartons;
// Kinematic factors
double xa;
double xb;
public:
// Constructor for class
njPhaseSpace(int n);
// Returns a vector of the outgoing parton momenta
std::vector <HLV> ReturnOutgoingPartons() {
return OutgoingPartons;
}
// HLV IncomingForward
} ;
// Class constructor - adds n vectors to the Outgoing array
njPhaseSpace::njPhaseSpace(int n) {
// Add n final states to the OutgoingPartons vector
for (int i = 0; i < n; i++) {
HLV temp;
OutgoingPartons.push_back(temp);
}
}
UPDATE: This problem goes away when the class constructor is included in the body of the class definition. Whilst its good I can avoid this it doesnt really help because now to develop my class everything will have to sit inside the definition.
UPDATE: The makefile used to compile (Analysis is something seperate I am currently running make Explorer -j8):
#/bin/bash
# CXX Compiler
CXX = g++
# Directories For Compilation
INCDIR = MadGraph
LIBDIR = MadGraph
SRCDIR = Source
# Compilation Flags
CXXFLAGS = -O3 -lm
LIBFLAGS = $(shell clhep-config --libs) $(shell fastjet-config --libs) $(shell clhep-config --libs) $(shell root-config --libs)
INCFLAGS = $(shell clhep-config --include) -I/$(INCDIR) -I$(SRCDIR) -I. $(shell fastjet-config --cxxflags --plugins) $(shell clhep-config --libs) $(shell root-config --cflags)
FLAGS = $(CXXFLAGS) $(LIBFLAGS) $(INCFLAGS)
# Object Files
Objects = $(addprefix $(SRCDIR)/, Currents.o mstwpdf.o LoadBar.o)
MadObjects = $(addprefix $(LIBDIR)/, HelAmps_sm.o Parameters_sm.o read_slha.o CPPProcess2j.o CPPProcess3j.o)
# Main targets
all: Analysis Explorer
Analysis: $(SRCDIR)/Analysis2jepem.cxx $(Objects) $(SRCDIR)/CGenerator2jepem.o
$(CXX) $(SRCDIR)/Analysis2jepem.cxx -o $# $(FLAGS) $(Objects) $(SRCDIR)/CGenerator2jepem.o
Explorer: $(SRCDIR)/qQepemqQ_Explorer.cxx $(Objects) $(MadObjects) $(LIBDIR)/libmodel_sm.a
$(CXX) $(SRCDIR)/qQepemqQ_Explorer.cxx -o $# $(FLAGS) $(Objects) -lmodel_sm -L$(LIBDIR)
# Build object files
$(Objects):
$(CXX) -c $(#:.o=.cxx) -o $#
# Build the MG5 object code
$(MadObjects):
$(CXX) -c $(#:.o=.cxx) -o $# -I../
$(SRCDIR)/CGenerator2jepem.o:
$(CXX) -c $(#:.o=.cxx) -o $#
# Build the Standard Model library
$(LIBDIR)/libmodel_sm.a: $(MadObjects)
$(AR) cru $# $^
ranlib $#
# Debugging flags
debug: CXX += -g -Wall -pendantic
debug: all
# Create a clean build
.PHONY: clean
clean:
rm -f $(Objects) $(MadObjects) $(LIBDIR)/2j/libmodel_sm.a $(LIBDIR)/3j/libmodel_sm.a $(TARGET) $(SRCDIR)/CGenerator2jepem.o Analysis Explorer
The problem is that the class constructor is defined in the header file as:
njPhaseSpace::njPhaseSpace(int n) {
// Add n final states to the OutgoingPartons vector
for (int i = 0; i < n; i++) {
HLV temp;
OutgoingPartons.push_back(temp);
}
Either put it in the class declaration, or into it's own separate .cpp file that is compiled and linked separately.
This is no different from creating a non-inline/non-static/non anonymous namespaced function in a .h file and #including it in multiple .cpp files.
This error is sometimes prompted if you include the files like this:
File a included in file b;
Filb and file a included in file c.
Can you try to put the "static" keyword in front of the class constructor that gives you problems?
Related
Good morning,
I new in c++ and I am trying to compile my simple code to executable form. I will explain structure of project.
- main.cpp
- /utility/server.h
- /utility/server.cpp
I enclose file sources for complete information.
main.cpp
#include <iostream>
#include "utility/server.h"
using namespace std;
using namespace server;
int main() {
std::cout << "Content-type:text/html\r\n\r\n";
std::cout << "Your server name is: " << server::get_domain() << '\n';
return 0;
}
server.cpp
#include <cstdlib>
#include "server.h"
namespace server {
static char* get_domain() {
return getenv("SERVER_NAME");
}
}
To my Makefile I added comments to understand what I want to do.
#
# 'make' build executable file
# 'make clean' removes all .o and executable files
#
# define the C compiler to use
CC = g++
# define any compile-time flags
CFLAGS = -Wall -g
# define any directories containing header files other than /usr/include
INCLUDES = -I../utility
# define the C++ source files
SRCS = main.cpp utility/server.cpp
# define the C++ object files
OBJS = $(SRCS:.cpp=.o)
# define the executable file
MAIN = executable.cgi
#
# The following part of the makefile is generic
#
.PHONY: depend clean
all: $(MAIN)
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS)
# this is a suffix replacement rule for building .o's from .cpp's
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -cpp $< -o $#
clean:
$(RM) *.o *~ $(MAIN)
depend: $(SRCS)
makedepend $(INCLUDES) $^
And finally error from compilation
g++ -Wall -g -I../utility -o executable.cgi main.o utility/server.o
Undefined symbols for architecture x86_64:
"server::get_domain()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [executable.cgi] Error 1
From error message I understood there is problem with utility folder, but I don't know how to fix it.
Thank you for your help :)
In server.cpp, here:
namespace server {
static char* get_domain() {
return getenv("SERVER_NAME");
}
}
You have made char* server::get_domain() a static function, making
its definition visible only within this translation unit and invisible to
the linker. Remove the keyword static here, and also in server.h if you have declared the function static there.
A namespace is not a class or struct. Confusingly,
namespace server {
static char* get_domain() {
return getenv("SERVER_NAME");
}
}
server::get_domain() is a static function in that namespace. But
struct server {
static char* get_domain() {
return getenv("SERVER_NAME");
}
};
it is a global function in that class, which the linker can see.
THE FILES
foo.hpp
#include <iostream>
class foo
{
public:
foo(int = 1);
int get_x() const { return x; }
private:
int x;
};
foo.cpp
#include "foo.hpp"
foo::foo(int xp)
{
x = xp;
}
main.cpp
#include "foo.hpp"
int main()
{
foo bar;
std::cout << bar.get_x() << std::endl;
}
Makefile (this is overkill for such a simple example, but I want to use something like this)
SHELL = /bin/bash
CC = g++
CPPFLAGS = -MMD -MP
SRC = $(wildcard *.cpp)
OBJ = $(SRC:.cpp=.o)
EXECUTABLE = main
all: $(SRC) $(EXECUTABLE)
$(EXECUTABLE): $(OBJ)
$(CC) $(OBJ) -o $#
.cpp.o:
$(CC) $(CPPFLAGS) -c $^
-include $(SRC:.cpp=.d)
OBSERVED BEHAVIOR
The files are 20K. Run make, output is 1 and files are 48K. Now change default argument int = 1 in header file to int = 2.
make: output is 2 and files are 11M. Nearly all of that is in foo.hpp.gch. Change int = 2 to int = 3.
make: output is still 2, foo.hpp.gch did not update.
Now if I move #include <iostream> out of foo.hpp and into main.cpp:
Files are 20K. Run make, output is 1 and files are 48K. Change int = 1 to int = 2.
make: output is 2 and files are 1.9M, nearly all of that in foo.hpp.gch. Change int = 2 to int = 3.
make: output is 3, foo.hpp.gch did update.
QUESTIONS
Why does make update a precompiled header (.gch) in one case, but not in the other? Why are the file sizes so different? What happened to the content of iostream? And how can I force make to always take into account changes in header files? I tried adding -fsyntax-only to CPPFLAGS, per this answer, but that gave an error.
To partially answer my own question, in the Makefile I changed $^ to -o $# $< and that seems to fix everything. The header files now update every time, and the combined files are only 144K. I got this idea here.
My C++ program consists of three files:
two source files 'main.cpp' and 'hellolib.cpp'
a header file 'hellolib.h'
I am creating a makefile for this program. For my assignment I need one target ('hello') that compiles all source files in an executable.
Another target ('obj') should compile all '.cpp' files into objects and link them together in an executable.
When running make I prefer the object files to be created in a seperate folder called 'bin'. The source files are would be in a folder called 'src'. These folders are siblings, the makefile is in it's parent folder.
My makefile works fine but I wish two combine the two targets 'bin/main.o' and 'bin/hellolib.o' into one to reduce the amount of rules, especially for later when I am dealing with more source files.
I imagined the replacement would look something like this, but it doesn't seem to work.
It gives me the error: "*** No rule ot make target 'bin/main.o',
needed by 'obj'. Stop.
bin/%.o : src/%.cpp
$(CC) -c $< -o $#
Working Makefile:
CC = g++
SOURCES = ./src/main.cpp \
./src/hellolib.cpp
OBJECTS = ./bin/main.o \
./bin/hellolib.o
hello : $(SOURCES)
$(CC) -o $# $^
obj : $(OBJECTS)
$(CC) -o $# $^
bin/main.o : src/main.cpp
$(CC) -c $< -o $#
bin/hellolib.o : src/hellolib.cpp
$(CC) -c $< -o $#
clean:
#rm -rf hello obj bin/*.o
main.cpp:
#include "hellolib.h"
int main() {
Hello h("Name");
h.Print();
return 0;
}
hellolib.cpp
#include "hellolib.h"
#include <iostream>
Hello::Hello(std::string name) {
if (name.empty()) {
cout << "Name is not valid!";
return;
}
_name = name;
}
void Hello::Print() {
cout << "Hello " << _name << endl;
}
hellolib.h
#ifndef HELLO_LIB_H
#define HELLO_LIB_H
#include <string>
using namespace std;
class Hello {
std::string _name;
public:
Hello(std::string name);
void Print();
};
#endif
You need to change:
OBJECTS = ./bin/main.o \
./bin/hellolib.o
to:
OBJECTS = bin/main.o \
bin/hellolib.o
(Removing leading "./"). Either that, or change your pattern rule to include the leading "./":
./bin/%.o : src/%.cpp
$(CC) -c $< -o $#
Make rule matching uses text matching. It's not based on filenames, so "./././foo" and "foo" are not the same thing.
Personally I recommend rewriting like this:
SOURCES = src/main.cpp \
src/hellolib.cpp
OBJECTS = $(patsubst src/%.cpp,bin/%.o,$(SOURCES))
so you only need to keep the list of files in one place.
You can make a rule that builds anything conforming to a specific pattern like this:
bin/%.o : src/%.cpp
$(CC) -c -o $# $<
That will compile any bin/%.o dependency from the corresponding source src/%.cpp.
Also it is standard when compiling C++ to use CXX rather than CC (which is for C code).
I am trying to use shared_ptr in c++. I am using MinGw gcc compiler.
My g++ version is 4.8.1.
When I try to use std::shared_ptr, it says it does not name a type.
Is this because it is part of c++ 11, and that is not supported in the compiled I am using?
Or do I need to set a flag to use c++ 11 features?
EDIT: I tried adding the flag to enable c++ to my makefile, and it still gives an error.
My header where shared_ptr is used is as follows
#pragma once
#include <vector>
#include <memory>
namespace WavFileTools
{
class WavFile;
}
class WavFileTools::WavFile
{
public:
typedef std::vector<unsigned char> PCMData8_t;
typedef std::vector<unsigned short int> PCMData16_t;
struct WavFileHeader {
int num_channels;
int sample_rate;
int bits_per_sample;
};
static std::shared_ptr<WavFile> LoadWavFromFile(std::string filename);
private:
WavFile(void);
private:
WavFileHeader m_header;
PCMData16_t m_data16;
PCMData8_t m_data8;
};
And the makefile...
CC := g++
CFLAGS := -g -O2 -std=c++0x
BIN_DIR := bin
BUILD_DIR := build
SRC_DIR := src
MAIN := WavFileTool
TARGET := wavfiletool.exe
SOURCES := $(wildcard src/*.cpp)
OBJECTS := $(SOURCES:$(SRC_DIR)/%.cpp=$(BUILD_DIR)/%.o)
$(BIN_DIR)/$(TARGET): CREATE_DIRS $(BUILD_DIR)/$(MAIN).o $(OBJECTS)
$(CC) $(OBJECTS) $(CFLAGS) -o $#
$(BUILD_DIR)/$(MAIN).o: $(SRC_DIR)/WavFileTool.cpp
$(CC) $(CFLAGS) -c -o $# $<
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
$(CC) $(CC_FLAGS) -c -o $# $<
CREATE_DIRS:
if not exist $(BIN_DIR) mkdir $(BIN_DIR)
if not exist $(BUILD_DIR) mkdir $(BUILD_DIR)
CLEAN:
if exist $(BIN_DIR) rmdir /Q /S $(BIN_DIR) # /S allows deleting non-empty folder, and /Q prevents confirmation required
if exist $(BUILD_DIR) rmdir /Q /S $(BUILD_DIR)
and the error
In file included from src/WavFile.cpp:1:0:
src/WavFile.h:26:10: error: 'shared_ptr' in namespace 'std' does not name a type
static std::shared_ptr<WavFile> LoadWavFromFile(std::string filename);
I read different answers about VLA on SO but couldn't find the answer. In my case, I have one function that allocates memory:
template<typename T>
void allocMemory(T *&data, const size_t numElems)
{
#ifdef PINNED_MEMORY
// allocate pinned memory
#else
data = new T[numElems];
#endif
}
Now, I have a vector class where I use this method:
template<typename T>
class MyVec
{
T *data;
size_t size;
public:
MyVec(size_t _size): size(_size)
{ allocMemory<T>(data, size); } // gives VLA warning
};
It happens when I compile it using nvcc (V0.2.1221) compiler which I guess uses gcc compiler underneath (?) The actual warning is:
myvec.h:16:6: warning: ISO C++ does not support variable-length array types [-Wvla]
data = new T[numElems];
I think you don't compile your project the right way.
Try to using the flowing make file.
CUDA_INSTALL_PATH := /usr/local/cuda
CXX := g++
CC := gcc
LINK := g++ -fPIC
NVCC := nvcc
#Includes
INCLUDES = -I. -I$(CUDA_INSTALL_PATH)/include
#Common flags
COMMONFLAGS += $(INCLUDES)
NVCCFLAGS += $(COMMONFLAGS)
CXXFLAGS += $(COMMONFLAGS)
CFLAGS += $(COMMONFLAGS)
LIB_CUDA := -L$(CUDA_INSTALL_PATH)/lib -lcudart
#OBJS = GpuSolver.cu.o main.cpp.o
OBJS = main.cu.o a.cpp.o # your files
TARGET = a.out
LINKLINE = $(LINK) -o $(TARGET) $(OBJS) $(LIB_CUDA)
.SUFFIXES: .c .cpp .cu .o
%.c.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
.cu.o: %.cu
$(NVCC) $(NVCCFLAGS) -c $< -o $#
%.cpp.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
$(TARGET): $(OBJS) "makefile" #your makefile file name
$(LINKLINE)