Undefined reference in c... What am I doing wrong? - c++

I have the following code... which is throwing a main.cpp:18: undefined reference to phrase_init() Coming from C# experience C is a bit annoying especially when trying to figure out where the problem is :( Any idea or pointer will be greatly appreciated!
phrase.h:
#ifndef PHRASE_H
#define PHRASE_H
typedef struct
{
char* Word1;
char* Word2;
} Phrase;
Phrase* phrase_init(void);
#endif
Phrase.c :
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "phrase.h"
Phrase* phrase_init()
{
Phrase* phrase = (Phrase *)malloc(sizeof(Phrase));
phrase->Word1 = (char *)malloc(sizeof(char));
phrase->Word2 = (char *)malloc(sizeof(char));
return phrase;
}
main.c
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <iomanip>
#include <cctype>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include "phrase.h"
int main(int argc, char** argv) {
char* word1 = "Testing";
char* word2 = "Word2";
Phrase* test = phrase_init();
strcpy(test->Word1, word1);
strcpy(test->Word2, word2);
printf("Word 1: %s", test->Word1);
printf("Word 2: %s", test->Word2);
scanf("%s", word1);
}
Makefile:
#
# There exist several targets which are by default empty and which can be
# used for execution of your targets. These targets are usually executed
# before and after some main targets. They are:
#
# .build-pre: called before 'build' target
# .build-post: called after 'build' target
# .clean-pre: called before 'clean' target
# .clean-post: called after 'clean' target
# .clobber-pre: called before 'clobber' target
# .clobber-post: called after 'clobber' target
# .all-pre: called before 'all' target
# .all-post: called after 'all' target
# .help-pre: called before 'help' target
# .help-post: called after 'help' target
#
# Targets beginning with '.' are not intended to be called on their own.
#
# Main targets can be executed directly, and they are:
#
# build build a specific configuration
# clean remove built files from a configuration
# clobber remove all built files
# all build all configurations
# help print help mesage
#
# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
# .help-impl are implemented in nbproject/makefile-impl.mk.
#
# Available make variables:
#
# CND_BASEDIR base directory for relative paths
# CND_DISTDIR default top distribution directory (build artifacts)
# CND_BUILDDIR default top build directory (object files, ...)
# CONF name of current configuration
# CND_PLATFORM_${CONF} platform name (current configuration)
# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
#
# NOCDDL
# Environment
MKDIR=mkdir
CP=cp
CCADMIN=CCadmin
# build
build: .build-post
.build-pre:
# Add your pre 'build' code here...
.build-post: .build-impl
# Add your post 'build' code here...
# clean
clean: .clean-post
.clean-pre:
# Add your pre 'clean' code here...
.clean-post: .clean-impl
# Add your post 'clean' code here...
# clobber
clobber: .clobber-post
.clobber-pre:
# Add your pre 'clobber' code here...
.clobber-post: .clobber-impl
# Add your post 'clobber' code here...
# all
all: .all-post
.all-pre:
# Add your pre 'all' code here...
.all-post: .all-impl
# Add your post 'all' code here...
# build tests
build-tests: .build-tests-post
.build-tests-pre:
# Add your pre 'build-tests' code here...
.build-tests-post: .build-tests-impl
# Add your post 'build-tests' code here...
# run tests
test: .test-post
.test-pre:
# Add your pre 'test' code here...
.test-post: .test-impl
# Add your post 'test' code here...
# help
help: .help-post
.help-pre:
# Add your pre 'help' code here...
.help-post: .help-impl
# Add your post 'help' code here...
# include project implementation makefile
include nbproject/Makefile-impl.mk
# include project make variables
include nbproject/Makefile-variables.mk

You have to tell the linker where to find the symbol.
For example:
g++ -c phrase.cpp # creates phrase.o which defines phrase_init()
g++ -c main.cpp # creates main.o which refers to phrase_init()
g++ phrase.o main.o -o main # creates executable file "main"
Or, to do all of the above in one command:
g++ phrase.cpp main.cpp -o main
Note that I'm assuming both source files are C++, and are named with .cpp extensions. Your question refers to files with both .c and .cpp extensions, and the question is tagged c++.
If you're using C, then you shouldn't be using C++-specific headers in main.c, and you should use gcc rather than g++.
If you're using C++, all your source files should have .cpp suffixes and you should used g++.
And if you're trying to mix C and C++, then you should be using extern "C" so the compiler knows what you're doing (but it's usually easier to use pure C++).

And you really should compile with -Wall -g so add to your Makefile
CXXFLAGS+= -Wall -g
CFLAGS+= -Wall -g
the first is for C++, the second is for C
I also think you should write by hand your own (simpler) Makefile for make (instead of copying a more complex Makefile that you don't understand).

Related

waf: Uselib options in custom rule

I have a waf build script and need to invoke a program which is not officially supported.
#file wscript
def configure(conf):
conf.env.LIB = ['c', 'd']
conf.env.INCLUDES = ['include']
conf.env.LIB_xml2 = ['xml2']
conf.env.INCLUDES_xml2 = ['/usr/include/libxml2']
def build(bld):
bld(rule="dstep ${SRC} -o ${TGT} ${LIB_ST:LIB} ${DINC_ST:INCLUDES}",
use="xml2",
source="header.h",
target="target.d",
)
This expands to dstep header.h -o target.d -lc -ld -I/usr/include/libxml2, so only the global LIB variable works, the use parameter seems to entirely ignored.
How can I make it respect the use parameter?
For waf to process the use keyword, you must add the use feature to your task generator. You also need to add a "compile" aware feature like c, d or cxx. Like this:
def build(bld):
bld(
rule="dstep ${SRC} -o ${TGT} ${LIB_ST:LIB} ${DINC_ST:INCLUDES}",
features = ["use", "c"],
use="xml2",
source="header.h",
target="target.d",
)
You can also program specifics for your dstep (You have to define a dstep feature and define the USELIB_VARS["dstep"])
Note: See ccroot.py in waf code.

Don't know how to build from a source file with suffix `.yy'. Expected a suffix in this list: ['.lm', '.ll']

I'm having an issue while building packages from source using scons. I'm getting the below exception. If I change the file extension to ll or lm
I get syntax errors while it compiles.
scons -j ${JOBS_COUNT:-$(grep -c processor /proc/cpuinfo || echo 1)} --without-dpdk
scons: Reading SConscript files ...
('Ubuntu', '20.04', 'focal')
('Ubuntu', '20.04', 'focal')
('Ubuntu', '20.04', 'focal')
scons: *** While building `['sandeshy.cc']' from `['/root/salim/src/contrail-common/sandesh/compiler/sandeshy.yy']': Don't know how to build from a source file with suffix `.yy'. Expected a suffix in this list: ['.lm', '.ll'].
Sconscript file
# -*- mode: python; -*-
#
# Created by Megh Bhatt on 07/16/12.
# Copyright (c) 2012 Contrail Systems. All rights reserved.
#
Import('SandeshEnv')
env = SandeshEnv.Clone();
rmflags = ['-Wsign-compare', '-Werror', '-fno-exceptions',
'--coverage']
cflags = env['CCFLAGS']
for flag in rmflags:
if flag in cflags:
cflags.remove(flag)
env['CCFLAGS'] = cflags
env.Append(CPPPATH = ['#src/contrail-common/sandesh/compiler','#build/include'])
# Lex and Yacc
env.Append(YACCFLAGS = '-d')
env['YACCHXXFILESUFFIX'] = '.hh'
#env.Append(LEXFLAGS = '-DSANDESH')
env.CXXFile(target = 'sandeshy.cc', source = 'sandeshy.yy')
env.CXXFile(target = 'sandeshl.cc', source = 'sandeshl.ll')
sandesh = env.Program(target = 'sandesh',
source = ['main.cc',
'md5.c',
'sandeshy.cc',
'sandeshl.cc',
'generate/t_cpp_generator.cc',
'generate/t_html_generator.cc',
'generate/t_generator.cc',
'generate/t_xsd_generator.cc',
'generate/t_c_generator.cc',
'generate/t_py_generator.cc',
'generate/t_doc_generator.cc',
'parse/parse.cc',
])
env.Install(env['TOP_BIN'], sandesh)
I am trying to build packages from opencontrail source files which is got from github repo
sandeshy.yy file located in github repo
You need to install yacc to fix this error, scons is presumably checking what it is able to process, as it can't process yacc files it doesn't add .yy to the list of supported extensions for CXXFile

Unit tests using Automake

I am working in a project with other people in the team using GNU autotools. In the project we are using unit test for each non trivial C++ class. I found out that there is support for unit testing. For that I am using this structure:
./
+ tests/
+ Makefile.am
+ classA_test.cc
....
+ classB_test.cc
+ src/
+ lib/
+ Makefile.am
The problem comes since my main Makefile.am is using subdir-objects options --note that I am not using recursive makefile for the source files--, I cannot export my variables --such as, AM_CPPFLAGS-- to the other Makefile. So far I made it work using:
$ make check
but I keep getting problems for the paths and the options when I do
$ make distcheck
So my questions is, how is the standard way to deal with unit tests?
EDIT:
I made it work as long as I remove the subdir-objects from the tests/Makefile.am. Now it throw some warnings but it compiles. Still it seems not to be an appropriate way to deal with unit tests
After some research I came up with the appropiate way to deal with Unit tests and Automake:
Following the previous scheme:
./
+ tests/
+ Makefile.am
+ classA_test.cc
....
+ classB_test.cc
+ src/
+ lib/
+ Makefile.am
The makefile.am in the root will be the main one, this one calls the makefile in the tests directory
$ cat Makefile.am
SUBDIRS = . tests # (Super Important) note the "." before tests,
# it means it will be executed first
....
$ cat test/Makefile.am
AM_CXXFLAGS = ...
AM_LDFLAGS = -L #top_srcdir#/lib #If needed
LDADD = -llibraryfortests #If needed
TESTS = test1 .. testN
test1_SOURCES = test1.cc ../src/somewhere/classtotest.cc
testN_SOURCES = ...
$ cat configure.ac
AM_INIT_AUTOMAKE([subdir-objects])
AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([tests/Makefile])
...
Now if you want to run the tests
$ sh ../pathto/configure
$ make check
As well dist[check] should work
$ make distcheck
...
make[3]: Entering directory `/home/vicente/test/tests'
PASS: settings
============================================================================
Testsuite summary for Pepinos 00.13.15
============================================================================
# TOTAL: 1
# PASS: 1
# SKIP: 0
# XFAIL: 0
# FAIL: 0
# XPASS: 0
# ERROR: 0
============================================================================
make[3]: Leaving directory `/home/vicente/test/tests'
...
So to answer the other question?
Q. I cannot export my variables --such as, AM_CPPFLAGS-- to the other Makefile.
A. True, but I can always declare a variable in the configure.ac and AC_SUBT to make it visible to other Makefile.am
Sources: https://stackoverflow.com/a/29255889/2420872

making qt ignore specific header include files

I have a running project made in qt . For building purpose I m using waf build tool. To get the same project up and running from waf I need to add
#include "file.moc"
at the end of some files to avoid undefined reference. But if these includes are not commented in qt I get can not find file errors. How do you make qt ignore certain file includes. I thought something like this should have done the trick
#ifndef Q_MOC_RUN
#include "file.moc"
#endif
Due to the limited information provided, all I can show is what waf can do:
You either can include the moc files or the unprocessed files.
Examples are included in the distributed source at https://code.google.com/p/waf/downloads/detail?name=waf-1.6.11.tar.bz2
Subdirectories:
playground/slow_qt/
demos/qt4/
For the sake of completness, simplified examples:
default includes
def options(opt):
opt.load('compiler_cxx qt4')
def configure(conf):
conf.load('compiler_cxx qt4')
conf.load('slow_qt4')
def build(bld):
bld(
features = 'qt4 cxx cxxprogram',
uselib = 'QTCORE QTGUI QTOPENGL QTSVG',
source = 'some.cpp files.cpp',
includes = '.',
target = 'dummy',
)
moc cpp
def options(opt):
opt.load('compiler_cxx qt4')
def configure(conf):
conf.load('compiler_cxx qt4')
def build(bld):
bld(
features = 'qt4 cxx cxxprogram',
uselib = 'QTCORE QTGUI QTOPENGL QTSVG',
source = 'some.cpp files.cpp',
target = 'dummy',
includes = '.')
)

Python scons building

Now I am studying an open source fluid simulation called pabalos. I have some problems building my own program that links against the library.
The library is built from source using scons.
The directory of the project is :
[fred#suck palabos-v1.1r0]$ls
codeblocks/ examples/ jlabos/ pythonic/ SConstruct utility/
COPYING externalLibraries/ lib/ scons/ src/
I will refer to this as the project root directory!
The project's official building documentation says:
The library Palabos makes use of an on-demand compilation process. The
code is compiled the first time it is used by an end-user application,
and then automatically re-used in future, until a new compilation is
needed due to a modification of the code or compilation options.
In the examples directory, there are some example code directories, such as :
[fred#suck palabos-v1.1r0]$ls examples/showCases/rectangularChannel3d/*
examples/showCases/rectangularChannel3d/Makefile
examples/showCases/rectangularChannel3d/rectangularChannel3D.cpp
The Makefile of the example is:
[fred#suck rectangularChannel3d]$cat Makefile
##########################################################################
## Makefile for the Palabos example program rectangularChannel3D.
##
## The present Makefile is a pure configuration file, in which
## you can select compilation options. Compilation dependencies
## are managed automatically through the Python library SConstruct.
##
## If you don't have Python, or if compilation doesn't work for other
## reasons, consult the Palabos user's guide for instructions on manual
## compilation.
##########################################################################
# USE: multiple arguments are separated by spaces.
# For example: projectFiles = file1.cpp file2.cpp
# optimFlags = -O -finline-functions
# Leading directory of the Palabos source code
palabosRoot = ../../..
# Name of source files in current directory to compile and link with Palabos
projectFiles = rectangularChannel3D.cpp
# Set optimization flags on/off
optimize = true
# Set debug mode and debug flags on/off
debug = false
# Set profiling flags on/off
profile = false
# Set MPI-parallel mode on/off (parallelism in cluster-like environment)
MPIparallel = true
# Set SMP-parallel mode on/off (shared-memory parallelism)
SMPparallel = false
# Decide whether to include calls to the POSIX API. On non-POSIX systems,
# including Windows, this flag must be false, unless a POSIX environment is
# emulated (such as with Cygwin).
usePOSIX = true
# Path to external libraries (other than Palabos)
libraryPaths =
# Path to inlude directories (other than Palabos)
includePaths =
# Dynamic and static libraries (other than Palabos)
libraries =
# Compiler to use without MPI parallelism
serialCXX = g++
# Compiler to use with MPI parallelism
parallelCXX = mpicxx
# General compiler flags (e.g. -Wall to turn on all warnings on g++)
compileFlags = -Wall -Wnon-virtual-dtor
# General linker flags (don't put library includes into this flag)
linkFlags =
# Compiler flags to use when optimization mode is on
optimFlags = -O3
# Compiler flags to use when debug mode is on
debugFlags = -g
# Compiler flags to use when profile mode is on
profileFlags = -pg
##########################################################################
# All code below this line is just about forwarding the options
# to SConstruct. It is recommended not to modify anything there.
##########################################################################
SCons = $(palabosRoot)/scons/scons.py -j 2 -f $(palabosRoot)/SConstruct
SConsArgs = palabosRoot=$(palabosRoot) \
projectFiles="$(projectFiles)" \
optimize=$(optimize) \
debug=$(debug) \
profile=$(profile) \
MPIparallel=$(MPIparallel) \
SMPparallel=$(SMPparallel) \
usePOSIX=$(usePOSIX) \
serialCXX=$(serialCXX) \
parallelCXX=$(parallelCXX) \
compileFlags="$(compileFlags)" \
linkFlags="$(linkFlags)" \
optimFlags="$(optimFlags)" \
debugFlags="$(debugFlags)" \
profileFlags="$(profileFlags)" \
libraryPaths="$(libraryPaths)" \
includePaths="$(includePaths)" \
libraries="$(libraries)"
compile:
python $(SCons) $(SConsArgs)
clean:
python $(SCons) -c $(SConsArgs)
/bin/rm -vf `find $(palabosRoot) -name '*~'`
I know this makefile will call scons, and SConstruct file is in the project root dir as I have shown.
The SContstruct file is :
[fred#suck palabos-v1.1r0]$cat SConstruct
###########################################################
# Configuration file for the compilation of Palabos code,
# using the SConstruct library.
# IT IS NOT RECOMMENDED TO MODIFY THIS FILE.
# Compilation should be personalized by adjusting the
# Makefile in the directory of the main source files.
# See Palabos examples for sample Makefiles.
###########################################################
import os
import sys
import glob
argdict = dict(ARGLIST)
# Read input parameters
palabosRoot = argdict['palabosRoot']
projectFiles = Split(argdict['projectFiles'])
optimize = argdict['optimize'].lower() == 'true'
debug = argdict['debug'].lower() == 'true'
profile = argdict['profile'].lower() == 'true'
MPIparallel = argdict['MPIparallel'].lower() == 'true'
SMPparallel = argdict['SMPparallel'].lower() == 'true'
usePOSIX = argdict['usePOSIX'].lower() == 'true'
serialCXX = argdict['serialCXX']
parallelCXX = argdict['parallelCXX']
compileFlags = Split(argdict['compileFlags'])
linkFlags = Split(argdict['linkFlags'])
optimFlags = Split(argdict['optimFlags'])
debugFlags = Split(argdict['debugFlags'])
profileFlags = Split(argdict['profileFlags'])
libraryPaths = Split(argdict['libraryPaths'])
includePaths = Split(argdict['includePaths'])
libraries = Split(argdict['libraries'])
# Read the optional input parameters
try:
dynamicLibrary = argdict['dynamicLibrary'].lower() == 'true'
except:
dynamicLibrary = False
try:
srcPaths = Split(argdict['srcPaths'])
except:
srcPaths = []
flags = compileFlags
allPaths = [palabosRoot+'/src'] + [palabosRoot+'/externalLibraries'] + includePaths
if optimize:
flags.append(optimFlags)
if debug:
flags.append(debugFlags)
flags.append('-DPLB_DEBUG')
if profile:
flags.append(profileFlags)
linkFlags.append(profileFlags)
if MPIparallel:
compiler = parallelCXX
flags.append('-DPLB_MPI_PARALLEL')
else:
compiler = serialCXX
if SMPparallel:
flags.append('-DPLB_SMP_PARALLEL')
if usePOSIX:
flags.append('-DPLB_USE_POSIX')
env = Environment ( ENV = os.environ,
CXX = compiler,
CXXFLAGS = flags,
LINKFLAGS = linkFlags,
CPPPATH = allPaths
)
if dynamicLibrary:
LibraryGen = env.SharedLibrary
else:
LibraryGen = env.Library
sourceFiles = []
for srcDir in glob.glob(palabosRoot+'/src/*'):
sourceFiles.extend(glob.glob(srcDir+'/*.cpp'))
for srcDir in srcPaths:
sourceFiles.extend(glob.glob(srcDir+'/*.cpp'))
sourceFiles.extend(glob.glob(palabosRoot+'/externalLibraries/tinyxml/*.cpp'));
if MPIparallel:
palabos_library = LibraryGen( target = palabosRoot+'/lib/plb_mpi',
source = sourceFiles )
else:
palabos_library = LibraryGen( target = palabosRoot+'/lib/plb',
source = sourceFiles )
local_objects = env.Object(source = projectFiles)
all_objects = local_objects + palabos_library
env.Program(all_objects, LIBS=libraries, LIBPATH=libraryPaths)
My problem is:
When I changed the source file rectangularChannel3D.cpp in the example dir,
and run make, the palabos library should not be rebuilt since I didn't change
the library project's source file (in the 'src' dir of the root dir) at all. But
actually the lib file "libplb.a" had been rebuilt!! So why?
I agree with Brady. Try contacting the project you're trying to build.
Alternatively, if you get no help from them, and/or really want to fix this yourself, SCons has a flag --debug=explain which will tell you why any object is being build/rebuilt.