OSX: GLUT window never appears - c++

I'm trying to run ORTS on my Mac for a school project. It was ostensibly written to be cross-platform, but I don't know if it was ever properly tested on OSX. After a great deal of difficulty, I managed to get it to compile, but it still doesn't quite work.
When I run the ortsg application, which is the OpenGL graphical interface, the terminal output indicates that the game starts up, loads its assets and runs correctly. However, the actual game window never appears. The only possible indication of any problem is the following message:
2011-11-23 16:52:33.513 ortsg[4565:107] GLUT Warning: glutInit being called a second time.
Other than that message, all of the output is exactly the same as what I see when running on my school's Slackware Linux machines, where the game runs fine. (Unfortunately it's rather inconvenient for me to do my work on those machines, hence my attempts to run it on OSX.) I can get rid of that warning by commenting out a call to glutInit in apps/ortsg/src/ortsg_main.C, which doesn't seem to introduce any other problems, but the game window is still never shown.
I can't seem to find reports of anyone having similar problems on Google. I don't expect anyone on SO will be intimately familiar with ORTS, so my questions are as follows:
Are there any common scenarios which might cause a GLUT window to not appear, particularly on OSX?
Does GLUT provide any facilities for debugging such problems?
Edit: As requested by JimN, here is some of the GLUT initialization code...
// From apps/ortsg/src/ortsg_main.C
int main(int argc, char **argv)
{
char mydir[81];
getcwd(mydir, 80);
glutInit(&argc, argv);
chdir(mydir);
// ...
}
// From libs/gfxclient/src/GfxInit.C
void glutVisibilityDebug(int state)
{
if(state == GLUT_VISIBLE)
cout << "Window is visible" << endl;
else if(state == GLUT_NOT_VISIBLE)
cout << "Window is invisible" << endl;
else
cout << "Window state unknown";
}
void GfxModule::init_GLUT_window()
{
cerr << "INITIALIZE GLUT WINDOW" << endl;
GfxGlutAdaptor::set_client(this);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_ALPHA);
// the window starts near the upper left corner of the screen
glutInitWindowPosition(opt.win_x, opt.win_y);
glutInitWindowSize(opt.win_w, opt.win_h);
// Open a window
glutCreateWindow(opt.title.c_str());
// Register the splash as the draw routing until
glutDisplayFunc (GfxGlutAdaptor::splash);
glutVisibilityFunc(glutVisibilityDebug);
if (opt.full_screen) glutFullScreen();
}
I added the glutVisibilityDebug function to see if I could determine what GLUT thinks the window's visibility state is, but none of my debug statements are ever printed. Something else just occurred to me which might help debug this. I tried at one point to replace glutDisplayFunc with a function which just printed "glutDislplayFunc called" to stderr. I noticed that the text was only printed when I quit the application.

I downloaded the daily snapshot from 26/11/2011, and then installed all dependencies using brew on my Mac.
Executed export OSTYPE=DARWIN followed by make init and make. There were several compilation problems which I fixed on this makefile:
# $Id: makefile 10648 2011-10-06 15:46:07Z mburo $
#
# This is an ORTS file (c) Michael Buro, licensed under the GPL
# This make file works for systems which use gcc
#
# - shell variable OSTYPE must be set in your shell rc file as follows:
#
# if LINUX matches uppercase($OSTYPE) => Linux
# if DARWIN matches => Mac OS X
# if CYGWIN matches => Cygwin (gcc on Windows)
# if MSYS matches => MinGW (gcc on Windows)
#
# check that value with echo $OSTYPE and set it in your shell resource
# file if above words don't match. Don't forget export OSTYPE when using sh or bash
#
# I use: OSTYPE=`uname`
#
# - ORTS_MTUNE = i686 athlon-xp pentium-m etc.
# if set, -mtune=$(ORTS_MTUNE) is added to compiler options
#
# - set GCC_PRECOMP to 1 if you want to use precompiled header files (gcc >= 3.4)
#
# - adjust SDL/X paths if necessary
#
# - for non-gcc compilers try -DHAS_TYPEOF=0 if typeof causes trouble
#
# - make MDBG=1 ... displays the entire compiler/linker invocation lines
#
# - make clean removes make generated files
# - make cleanobj removes all .o files
#
# - make [MODE=dbg] compiles targets in debug mode (no STL debug!)
#
# - make MODE=opt compiles with optimizations
#
# - make MODE=bp compiles with bprof info
#
# - make MODE=gprof compiles with gprof info
#
# - make MODE=stldbg compiles optimized stl debug version
#
# - make <app> creates application bin/<app> (omit prefix bin/ !)
# use periods in <app> in place of slashes for applications
# within subdirectories (e.g. "make rtscomp06.game2.simtest")
#
# - make list displays a list of all registered applications
#
# - make init creates necessary dep+bin+obj directories and links
#
# - make creates all applications
#
# - shell variable ORTS_MODE defines the default compile mode
# if not set, the passed MODE= parameter or dbg will be used, if MODE is not passed
# otherwise ORTS_MODE will be used
#
# issues:
#
# - all include files are used (only using library includes would be better)
#
# new:
#
# applications and libraries can now name their individual external library dependencies
# (libs + headers)
# see: apps/*/src/app.mk and libs/*/src/lib.mk, esp. libs/gfxclient/src/lib.mk
#
# todo: adjust mac/cygwin to new libary setting
# supported substrings of OSTYPE
# The following words must be uppercase
# If they are found in the uppercased OSTYPE variable
# the particular O/S matches
OSTYPE_LINUX := LINUX
OSTYPE_MAC := DARWIN
OSTYPE_CYGWIN := CYGWIN
OSTYPE_MINGW := MSYS
# convert OSTYPE to uppercase
OSTYPE := $(shell echo -n "$(OSTYPE)" | tr a-z A-Z )
#$(warning OSTYPE=$(OSTYPE))
#OSTYPE := LINUX
# -DOS_LINUX or -DOS_MAC or -DOS_CYGWIN is passed to g++
# also set: OS_LINUX, OS_CYGWIN, OS_MAC := 1 resp.
# MinGW uses OS_LINUX for now.
# tar file name
PROJ := orts
# directories to be excluded from snapshot tar file
# no longer needed SNAPSHOT_EXCLUDE := libs/mapabstr apps/mapabs apps/polypath apps/hpastar
# special targets
EXCL_INC := clean init cleanobj tar dep rmdeps list tar snapshot rpm
# libraries
#LIB_DIRS := kernel network serverclient gfxclient pathfind osl mapabstr path ortsnet ai/low dcdt/se dcdt/sr newpath
#LIB_DIRS := $(wildcard libs/*) libs/dcdt/se libs/dcdt/sr libs/ai/low
LIB_DIRS := $(wildcard libs/*/src) $(wildcard libs/*/*/src)
#$(warning LIBS $(LIB_DIRS))
# sub-projects
ifeq ("$(MAKECMDGOALS)","")
APP_DIRS := orts ortsg# built by default (do not edit)
else
APP_DIRS := $(MAKECMDGOALS)# build the passed on application
endif
FILT := $(filter $(EXCL_INC),$(MAKECMDGOALS))
ifneq ("$(FILT)","")
APP_DIRS :=
endif
#MAKECMDGOALS := compile_gch link_gch $(MAKECMDGOALS)
#$(warning making $(MAKECMDGOALS) ...)
# $(warning making $(APP_DIRS) ...)
.PHONY: all ALWAYS $(EXCL_INC) $(APP_DIRS) init
# where dependencies are stored (change also in dependency command (***) below)
#
DEP := dep
#$(error $(vp))
# make libraries and applications, make and link gch file first
all: all_end
# create tar file of the entire project
tar:
# $(MAKE) clean; cd ..; tar cfz ../$(PROJ).tgz $(PROJ)
# daily SVN snapshot
SVNROOT=svn://mburo#bodo1.cs.ualberta.ca:/all/pubsoft
snapshot:
rm -rf orts
mkdir orts
svn export $(SVNROOT)/orts/trunk orts/trunk
tar cfz $(PROJ).tgz orts
rm -rf orts
rm -rf orts_data
mkdir orts_data
svn export $(SVNROOT)/orts_data/trunk orts_data/trunk
tar cfz orts_data.tgz orts_data
rm -rf orts_data
CC := g++
CC_OPTS := -pipe -felide-constructors -fstrict-aliasing -Wno-deprecated
# -fno-merge-constants
#WARN := -Wall -W -Wundef
WARN := -Wall -W
#-Wold-style-cast
#ifneq ("$(OSTYPE)", "$(OSTYPE_MINGW)")
ifeq (,$(findstring $(OSTYPE_MINGW),$(OSTYPE)))
WARN += -Wundef
endif
OPT:=-O3
ifneq ("$(ORTS_MTUNE)","")
OPT:=$(OPT) -mtune=$(ORTS_MTUNE)
endif
OPT_FRAME := -fomit-frame-pointer
# default
AWK := gawk
EXE_SUFFIX :=
#ifeq ("$(OSTYPE)", "$(OSTYPE_MAC)")
ifneq (,$(findstring $(OSTYPE_MAC),$(OSTYPE)))
################### Mac OS X
OS_MAC := 1
MACROS := -DGCC -DOS_MAC -DHAS_TYPEOF=1 -DTRANSFORM_MOUSE_Y=0 -DMAC_OS_X_VERSION_MIN_REQUIRED=1040 -DTARGET_API_MAC_CARBON=1
USR_FRAME := /Library/Frameworks
SYS_FRAME := /System/Library/Frameworks
INC_OPTS += -I/usr/local/Cellar/sdl/1.2.14/include/SDL \
-I/usr/local/Cellar/sdl_net/1.2.7/include/SDL \
-I/usr/local/Cellar/glew/1.7.0/include/GL \
-I/usr/include/GL \
-L$(USR_FRAME) -L$(SYS_FRAME) -L/usr/local/Cellar/sdl/1.2.14/lib -L/usr/local/Cellar/sdl_net/1.2.7/lib -L/usr/local/lib
SHARED_LIBS0 := -lc -lz -lpthread \
-lSDL \
-lSDL_net \
-lSDLmain \
-framework Foundation \
-framework AppKit
AWK := awk
#WARN += -Wno-long-double
ifeq ("$(CPU)", "G5")
OPT += -mcpu=970 -mpowerpc64
endif
else
################### MinGW
#ifeq ("$(OSTYPE)", "$(OSTYPE_MINGW)")
ifneq (,$(findstring $(OSTYPE_MINGW),$(OSTYPE)))
OS_LINUX := 1
MACROS := -DOS_LINUX -DGCC -D_WIN32=1 -DTRANSFORM_MOUSE_Y=1 -DHAS_TYPEOF=1
MACROS += -DGLUT_NO_LIB_PRAGMA -DGLUT_NO_WARNING_DISABLE
INC_OPTS += -I/mingw/include/GL -I/local/include
SHARED_LIBS0 := -lm -lzlib1 -lmingw32 -lSDLmain -lSDL -lSDL_net -lpthreadGC2 -lstdc++
else
################### Linux | Cygwin
MACROS := -DGCC -DTRANSFORM_MOUSE_Y=1 -DHAS_TYPEOF=1
INC_OPTS += -I$(HOME)/include -I$(HOME)/include/GL -I/usr/include -I/usr/include/SDL -I/usr/local/include/SDL -I$(HOME)/usr/local/include/GL
# -I/home/dsk06/cscrs/c399/c399-software/include
#ifeq ("$(OSTYPE)", "$(OSTYPE_LINUX)")
ifneq (,$(findstring $(OSTYPE_LINUX),$(OSTYPE)))
################### Linux
OS_LINUX := 1
MACROS += -DOS_LINUX
#SHARED_LIBS0 += -L/usr/lib -L/usr/local/lib -L/usr/X11R6/lib -lm -lz -lSDLmain -lSDL -lSDL_net -lpthread -lGL -lGLU -lXi -lXmu -lglut -lGLEW $(MODEL_LIBS) -lstdc++
#SHARED_LIBS0 += -L$(HOME)/lib -lm -lz -lSDLmain -lSDL -lSDL_net -lpthread -lstdc++
SHARED_LIBS0 += -L$(HOME)/lib -lm -lz -lSDL -lSDL_net -lpthread -lstdc++
# -lefence
else
#ifeq ("$(OSTYPE)", "$(OSTYPE_CYGWIN)")
ifneq (,$(findstring $(OSTYPE_CYGWIN),$(OSTYPE)))
################## Cygwin
OS_CYGWIN := 1
EXE_SUFFIX:=.exe
MACROS += -DOS_CYGWIN -DSTDC_HEADERS=1 -DGLUT_IS_PRESENT=1
#-mno-cygwin
#INC_OPTS += -I/usr/include/mingw -I/usr/include/mingw/GL -I/usr/include
#$(warning "INC_OPTS=" $(INC_OPTS))
# fixme: /lib/SDL_main.o -> -lSDLmain (didn't get SDL to compile on Cygwin)
# adjust paths if necessary
SHARED_LIBS0 := -lSDL -lSDL_net -lpthread -lz -lstdc++
# GLEW not checked under cygwin!
else
# unknown OSTYPE
$(error "!!!!! unknown OSTYPE=$(OSTYPE) !!!!")
endif
endif
endif
endif
# default mode; if ORTS_MODE set, use it
# otherwise use MODE if passed, or dbg otherwise
ifeq ("$(ORTS_MODE)", "")
MODE := dbg
else
MODE := $(ORTS_MODE)
endif
OBJ_DIR := obj
CONFIG := config
SHARED_PROF_LIBS := $(SHARED_LIBS0)
SHARED_BP_LIBS := ~/lib/bmon.o $(SHARED_LIBS0)
OBJ_OPT := $(OBJ_DIR)/opt
OBJ_DBG := $(OBJ_DIR)/dbg
OBJ_SDBG := $(OBJ_DIR)/stldbg
OBJ_PROF:= $(OBJ_DIR)/prof
OBJ_BP := $(OBJ_DIR)/bp
OFLAGS := $(WARN) $(OPT) $(OPT_FRAME) # !!! -g added for 2007 competition
DFLAGS := $(WARN) -g -ggdb # -ftrapv
SDFLAGS := $(WARN) -g -ggdb -O -D_GLIBCXX_DEBUG # STL debug mode is SLOW!
PFLAGS := $(WARN) $(OPT) -pg -O
BPFLAGS := $(WARN) -g -ggdb -O2
ifeq ("$(MODE)", "opt")
FLAGS := $(OFLAGS) -DNDEBUG -Wuninitialized
#-DSCRIPT_DEBUG
STRIP := strip
OBJ := $(OBJ_OPT)
SHARED_LIBS := $(SHARED_LIBS0)
else
ifeq ("$(MODE)", "gprof")
FLAGS := $(PFLAGS) -DNDEBUG -Wuninitialized
STRIP := echo
OBJ := $(OBJ_PROF)
SHARED_LIBS := $(SHARED_PROF_LIBS)
else
ifeq ("$(MODE)", "bp")
FLAGS := $(BPFLAGS) -DNDEBUG -Wuninitialized
STRIP := echo
OBJ := $(OBJ_BP)
SHARED_LIBS := $(SHARED_BP_LIBS)
else
ifeq ("$(MODE)", "dbg")
FLAGS := $(DFLAGS)
STRIP := echo
OBJ := $(OBJ_DBG)
SHARED_LIBS := $(SHARED_LIBS0)
else
ifeq ("$(MODE)", "stldbg")
FLAGS := $(SDFLAGS)
STRIP := echo
OBJ := $(OBJ_SDBG)
SHARED_LIBS := $(SHARED_LIBS0)
else
# unknown MODE
$(error "!!!!! unknown MODE=$(MODE) !!!!")
endif
endif
endif
endif
endif
CCOPTS = $(CC_OPTS) $(MACROS) $(FLAGS) $(INC_OPTS) -DBOOST_STRICT_CONFIG
# -m32 for 32-bit applications
LD := $(CC) $(CCOPTS)
LDOPTS := $(FLAGS)
# line prefix
ifeq ("$(MDBG)", "")
VERBOSE=#
else
VERBOSE=
endif
# how to generate precompiled header file if GCC_PRECOMP=1
# otherwise, create dummy file
ALLH := All.H
ALLGCH := $(ALLH).gch
ALLGCHMODE := $(ALLGCH).$(MODE)
ifeq ("$(GCC_PRECOMP)", "1")
$(CONFIG)/$(ALLGCHMODE) : $(CONFIG)/$(ALLH)
# rm -rf $(CONFIG)/$(ALLGCH)
# echo "compile gch file"
$(VERBOSE) $(CC) $(CCOPTS) -c -o xxx1 $<
# mv xxx1 $#
# echo "link gch file"
$(VERBOSE) cd $(CONFIG); ln -sf $(ALLGCHMODE) $(ALLGCH)
else
$(CONFIG)/$(ALLGCHMODE) : $(CONFIG)/$(ALLH)
# echo "DUMMY GCH FILE"
$(VERBOSE) touch $#
endif
# link gch file to gchmode file
# depends on compiled header file
ifeq ("$(GCC_PRECOMP)", "1")
link_gch:
# echo "link gch file"
$(VERBOSE) cd $(CONFIG); ln -sf $(ALLGCHMODE) $(ALLGCH)
else
link_gch:
# echo "remove gch file"
# cd config ; rm -f $(ALLGCHMODE) $(ALLGCH)
endif
#===================================================================
# how to create dependency files
# add depfile (.d) as dependent file
# (***) (can't use $(DEP) in sed command because it contains / - so if DEP changes edit this line!
# also prepend object path for .o file
#
DEP_EXEC = $(VERBOSE) set -e; $(CC) -MM $(CCOPTS) $(INC_OPTS) $< | sed 's/$*\.o[ :]*/$(subst /,.,$(basename $<)).o dep\/$(#F) : /g' | $(AWK) '{ if (index($$1,".o") > 0) { print "$$(OBJ)/" $$0 ; } else { print $$0; } }' > $#; [ -s $# ] || rm -f $#OB
# how to compile source files
#
COMP_EXEC = $(VERBOSE) $(CC) $(CCOPTS) -c -o $# `pwd`/$<
#-------------------------------------
define create_sublib_rules2
$$(OBJ)/libs.$(subst /,.,$1).src.%.o : libs/$1/src/%.$2
# echo "comp($$(MODE)):" $$<
$$(COMP_EXEC)
$$(DEP)/libs.$(subst /,.,$1).src.%.d : libs/$1/src/%.$2
# echo dep: $$<
$$(DEP_EXEC)
endef
define create_sublib_rules
$(foreach ext,C c cpp m,$(eval $(call create_sublib_rules2,$1,$(ext))))
endef
#-------------------------------------
define create_subapp_rules2
$$(OBJ)/apps.$1.src.%.o : apps/$(subst .,/,$1)/src/%.$2
# echo "comp($$(MODE)):" $$<
$$(COMP_EXEC)
$$(DEP)/apps.$1.src.%.d : apps/$(subst .,/,$1)/src/%.$2
# echo dep: $$<
$$(DEP_EXEC)
endef
define create_subapp_rules
$(foreach ext,C c cpp,$(eval $(call create_subapp_rules2,$1,$(ext))))
endef
#===================================================================
# collect all source files, replace suffix by .o, and filter out *_main.o
# input: FILES
# output: O_FILES
define create_O_FILES
#FILES := $$(notdir $$(FILES))
C_FILES := $$(filter %.C, $$(FILES))
c_FILES := $$(filter %.c, $$(FILES))
cpp_FILES := $$(filter %.cpp, $$(FILES))
m_FILES :=
ifeq ("$(OSTYPE)","$(OSTYPE_MAC)")
#ifneq (,$(findstring $(OSTYPE_MAC),$(OSTYPE)))
m_FILES := $$(filter %.m, $$(FILES))
endif
O_FILES := $$(C_FILES:.C=.o) $$(c_FILES:.c=.o) $$(cpp_FILES:.cpp=.o) $$(m_FILES:.m=.o)
O_FILES := $$(subst /,.,$$(O_FILES))
O_FILES := $$(filter-out %_main.o, $$(O_FILES))
endef
# include all applications and dependencies (uses SHARED_LIBS for linking)
APP_SDIRS := $(subst .,/,$(APP_DIRS))
ifneq ("$(APP_DIRS)","")
#include $(patsubst %, apps/%/src/app.mk, $(APP_DIRS))
include $(patsubst %, apps/%/src/app.mk, $(APP_SDIRS))
endif
#$(warning lib_dirs="$(LIB_DIRS)")
vp := $(patsubst %, apps/%/src, $(APP_SDIRS)) \
$(patsubst %, libs/%/src, $(APP_LIBS)) \
# $(LIB_DIRS)
#vp := $(patsubst %, %/src, $(LIB_DIRS)) \
# $(patsubst %, apps/%/src, $(APP_DIRS))
INC_OPTS += -Iconfig $(addprefix -I, $(vp))
# new
INC_OPTS += $(LIB_EXT_HD) $(APP_EXT_HD)
# $(warning INC_OPTS= $(INC_OPTS))
# where source files are searched
#$(warning vp="$(vp)")
vpath %.C $(vp)
vpath %.c $(vp)
vpath %.cpp $(vp)
vpath %.m $(vp)
all_end: link_gch $(APP_DIRS)
cleanobj:
rm -f $(OBJ_OPT)/*
rm -f $(OBJ_DBG)/*
rm -f $(OBJ_SDBG)/*
rm -f $(OBJ_PROF)/*
rm -f $(OBJ_BP)/*
clean:
( rm -f bin/*; exit 0)
rm -f $(DEP)/*
rm -f $(OBJ_OPT)/*
rm -f $(OBJ_DBG)/*
rm -f $(OBJ_SDBG)/*
rm -f $(OBJ_PROF)/*
rm -f $(OBJ_BP)/*
rm -f $(CONFIG)/*.gch*
rm -rf misc/doxygen/html
find . -name "*.bprof" -exec rm -f '{}' \;
find . -name ".ui" -exec rm -f '{}'/* \;
find . -name ".moc" -exec rm -f '{}'/* \;
rmdeps:
# rm -f $(DEP)/
rpm:
cd misc/pkgs/fc7; ./makerpm; cd ../../..
# create dependency, object directories
# doesn't touch links (pointing to fast local partitions)
init:
# echo "create directories"
# config/create_dir bin
# config/create_dir $(DEP)
# config/create_dir $(OBJ_DIR)
# config/create_dir $(OBJ_OPT)
# config/create_dir $(OBJ_DBG)
# config/create_dir $(OBJ_SDBG)
# config/create_dir $(OBJ_PROF)
# config/create_dir $(OBJ_BP)
# # ln -s ../../orts_data/trunk orts_data
# (cd libs/pathfinding/dcdt; ./makelinks; exit 0) > /dev/null 2>&1
Then some changes I had to do manually, to fix errors like:
sr_bv_math.cpp:561: error: ‘isnan’ was not declared in this scope
Edit the file trunk/libs/pathfinding/dcdt/sr/src/sr_bv_math.cpp and right after the cmath include, declare isnan as extern:
#include <cmath>
extern "C" int isnan(double);
That compiled the binaries, but then I had to also download orts_data.tgz to run the applications.
Well, running ortsg for the very first time failed, reporting:
texture size = 64X64
REMARK: can't open file: testgame/ortsg/terrain.tga
REMARK: can't open file: testgame/ortsg/noise.tga
Unable to load terrain noise texture testgame/ortsg/noise.tga
ERROR: /Users/karlphillip/installers/orts/orts/trunk/libs/gfxclient/src/GfxTerrain.C GfxTerrain() (line 213): failed to load noise image testgame/ortsg/noise.tga
REMARK: closing connection
REMARK: !!! already closed
REMARK: ~IO_Buffer called
Even though the files are there. So I KILLED the application and tried it again:
2011-11-27 01:51:02.947 ortsg[390:903] GLUT Warning: glutInit being called a second time.
seed=1322365862
ERROR: /Users/karlphillip/installers/orts/orts/trunk/libs/network/src/TCP_Client.C connect() (line 27): can't connect
REMARK: mixer not open
REMARK: closing connection
REMARK: !!! already closed
/Users/karlphillip/installers/orts/orts/trunk/libs/network/src/TCP_Client.C connect() (line 27): can't connect
Abort trap
The first line of the error might be familiar to you. Even though the app was killed, something seems to be left hanging somewhere, and the only way I found to bypass the error and have a clean run of the application was rebooting my computer.
It seems this application has issues on Mac OS X and need immediate fixing. I suggest you install a Linux VM, or even a Windows VM inside your Mac to be able to run orts, if you really have to use it.

Related

Makefile error when building Veins project with Omnet++

I've built a number of projects with Veins on Omnet++ without issues at this stage, and I decided to implement CAM messages into a simulation. However, upon building I arrive at the following error:
12:41:23 **** Incremental Build of configuration release for project v2x ****
make MODE=release all
cd src && make make[1]: Entering directory '/home/veins/workspace.omnetpp/v2x/src'
Creating executable: ../out/clang-release/src/v2x /usr/bin/ld: cannot open output file ../out/clang-release/src/v2x: Is a directory
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]:
*** [Makefile:117: ../out/clang-release/src/v2x] Error 1 make[1]: Leaving directory '/home/veins/workspace.omnetpp/v2x/src'
make: *** [Makefile:2: all]
Error 2 "make MODE=release all" terminated with exit code 2.
Build might be incomplete.
12:41:24 Build Failed. 3 errors, 0 warnings. (took 549ms)
My Makefile reads:
#
# OMNeT++/OMNEST Makefile for v2x
#
# This file was generated with the command:
# opp_makemake -f --deep -KINET_PROJ=/home/veins/src/inet -KLTE_PROJ=/home/veins/src/simulte -KVEINS_INET_PROJ=/home/veins/src/veins/subprojects/veins_inet -KVEINS_PROJ=/home/veins/src/veins -DINET_IMPORT -DVEINS_IMPORT -DVEINS_INET_IMPORT -I$$\(INET_PROJ\)/src -I$$\(LTE_PROJ\)/src -I$$\(VEINS_INET_PROJ\)/src -I$$\(VEINS_PROJ\)/src -I. -L$$\(INET_PROJ\)/src -L$$\(LTE_PROJ\)/src -L$$\(VEINS_PROJ\)/src -L$$\(VEINS_INET_PROJ\)/src -lINET$$\(D\) -llte$$\(D\) -lveins$$\(D\) -lveins_inet$$\(D\)
#
# Name of target to be created (-o option)
TARGET_DIR = .
TARGET_NAME = v2x$(D)
TARGET = $(TARGET_NAME)$(EXE_SUFFIX)
TARGET_IMPLIB = $(TARGET_NAME)$(IMPLIB_SUFFIX)
TARGET_IMPDEF = $(TARGET_NAME)$(IMPDEF_SUFFIX)
TARGET_FILES = $(TARGET_DIR)/$(TARGET)
# User interface (uncomment one) (-u option)
USERIF_LIBS = $(ALL_ENV_LIBS) # that is, $(TKENV_LIBS) $(QTENV_LIBS) $(CMDENV_LIBS)
#USERIF_LIBS = $(CMDENV_LIBS)
#USERIF_LIBS = $(TKENV_LIBS)
#USERIF_LIBS = $(QTENV_LIBS)
# C++ include paths (with -I)
INCLUDE_PATH = -I$(INET_PROJ)/src -I$(LTE_PROJ)/src -I$(VEINS_INET_PROJ)/src -I$(VEINS_PROJ)/src -I.
# Additional object and library files to link with
EXTRA_OBJS =
# Additional libraries (-L, -l options)
LIBS = $(LDFLAG_LIBPATH)$(INET_PROJ)/src $(LDFLAG_LIBPATH)$(LTE_PROJ)/src $(LDFLAG_LIBPATH)$(VEINS_PROJ)/src $(LDFLAG_LIBPATH)$(VEINS_INET_PROJ)/src -lINET$(D) -llte$(D) -lveins$(D) -lveins_inet$(D)
# Output directory
PROJECT_OUTPUT_DIR = ../out
PROJECTRELATIVE_PATH = src
O = $(PROJECT_OUTPUT_DIR)/$(CONFIGNAME)/$(PROJECTRELATIVE_PATH)
# Object files for local .cc, .msg and .sm files
OBJS = \
$O/v2x/GeneralMessageSerializer.o \
$O/v2x/VeinsInetApplicationBase.o \
$O/v2x/VeinsInetManager.o \
$O/v2x/VeinsInetManagerBase.o \
$O/v2x/VeinsInetManagerForker.o \
$O/v2x/VeinsInetMobility.o \
$O/v2x/VeinsInetSampleApplication.o \
$O/v2x/VeinsInetSampleMessageSerializer.o \
$O/v2x/GeneralMessage_m.o \
$O/v2x/VeinsInetSampleMessage_m.o
# Message files
MSGFILES = \
v2x/GeneralMessage.msg \
v2x/VeinsInetSampleMessage.msg
# SM files
SMFILES =
# Other makefile variables (-K)
INET_PROJ=/home/veins/src/inet
LTE_PROJ=/home/veins/src/simulte
VEINS_INET_PROJ=/home/veins/src/veins/subprojects/veins_inet
VEINS_PROJ=/home/veins/src/veins
#------------------------------------------------------------------------------
# Pull in OMNeT++ configuration (Makefile.inc)
ifneq ("$(OMNETPP_CONFIGFILE)","")
CONFIGFILE = $(OMNETPP_CONFIGFILE)
else
CONFIGFILE = $(shell opp_configfilepath)
endif
ifeq ("$(wildcard $(CONFIGFILE))","")
$(error Config file '$(CONFIGFILE)' does not exist -- add the OMNeT++ bin directory to the path so that opp_configfilepath can be found, or set the OMNETPP_CONFIGFILE variable to point to Makefile.inc)
endif
include $(CONFIGFILE)
# Simulation kernel and user interface libraries
OMNETPP_LIBS = $(OPPMAIN_LIB) $(USERIF_LIBS) $(KERNEL_LIBS) $(SYS_LIBS)
ifneq ($(PLATFORM),win32.x86_64)
LIBS += -Wl,-rpath,$(abspath $(INET_PROJ)/src) -Wl,-rpath,$(abspath $(LTE_PROJ)/src) -Wl,-rpath,$(abspath $(VEINS_PROJ)/src) -Wl,-rpath,$(abspath $(VEINS_INET_PROJ)/src)
endif
COPTS = $(CFLAGS) $(IMPORT_DEFINES) -DINET_IMPORT -DVEINS_IMPORT -DVEINS_INET_IMPORT $(INCLUDE_PATH) -I$(OMNETPP_INCL_DIR)
MSGCOPTS = $(INCLUDE_PATH)
SMCOPTS =
# we want to recompile everything if COPTS changes,
# so we store COPTS into $COPTS_FILE (if COPTS has changed since last build)
# and make the object files depend on it
COPTS_FILE = $O/.last-copts
ifneq ("$(COPTS)","$(shell cat $(COPTS_FILE) 2>/dev/null || echo '')")
$(shell $(MKPATH) "$O")
$(file >$(COPTS_FILE),$(COPTS))
endif
#------------------------------------------------------------------------------
# User-supplied makefile fragment(s)
-include makefrag
#------------------------------------------------------------------------------
# Main target
all: $(TARGET_FILES)
$(TARGET_DIR)/% :: $O/%
#mkdir -p $(TARGET_DIR)
$(Q)$(LN) $< $#
ifeq ($(TOOLCHAIN_NAME),clang-msabi)
-$(Q)-$(LN) $(<:%.dll=%.lib) $(#:%.dll=%.lib) 2>/dev/null
endif
$O/$(TARGET): $(OBJS) $(wildcard $(EXTRA_OBJS)) Makefile $(CONFIGFILE)
#$(MKPATH) $O
#echo Creating executable: $#
$(Q)$(CXX) $(LDFLAGS) -o $O/$(TARGET) $(OBJS) $(EXTRA_OBJS) $(AS_NEEDED_OFF) $(WHOLE_ARCHIVE_ON) $(LIBS) $(WHOLE_ARCHIVE_OFF) $(OMNETPP_LIBS)
.PHONY: all clean cleanall depend msgheaders smheaders
.SUFFIXES: .cc
$O/%.o: %.cc $(COPTS_FILE) | msgheaders smheaders
#$(MKPATH) $(dir $#)
$(qecho) "$<"
$(Q)$(CXX) -c $(CXXFLAGS) $(COPTS) -o $# $<
%_m.cc %_m.h: %.msg
$(qecho) MSGC: $<
$(Q)$(MSGC) -s _m.cc -MD -MP -MF $O/$(basename $<)_m.h.d $(MSGCOPTS) $?
%_sm.cc %_sm.h: %.sm
$(qecho) SMC: $<
$(Q)$(SMC) -c++ -suffix cc $(SMCOPTS) $?
msgheaders: $(MSGFILES:.msg=_m.h)
smheaders: $(SMFILES:.sm=_sm.h)
clean:
$(qecho) Cleaning $(TARGET)
$(Q)-rm -rf $O
$(Q)-rm -f $(TARGET_FILES)
$(Q)-rm -f $(call opp_rwildcard, . , *_m.cc *_m.h *_sm.cc *_sm.h)
cleanall:
$(Q)$(CLEANALL_COMMAND)
$(Q)-rm -rf $(PROJECT_OUTPUT_DIR)
help:
#echo "$$HELP_SYNOPSYS"
#echo "$$HELP_TARGETS"
#echo "$$HELP_VARIABLES"
#echo "$$HELP_EXAMPLES"
# include all dependencies
-include $(OBJS:%=%.d) $(MSGFILES:%.msg=$O/%_m.h.d)
It's correct in saying that clang-release/src/v2x is a directory, but it has always been so (even before making the recent changes) and it hasn't produced this error.
Other than the MakeFile error, there is no other error in any of the scripts for the project.
You want to create the executable file clang-release/src/v2x but you can't because that file already exists and is a directory.
The name of the file you attempt to create is
v2x$(D)$(EXE_SUFFIX) and nowhere in your Makefile do you have Make variables D or EXE_SUFFIX defined, so they evaluate to empty strings.
Probably you want to make sure you have D and EXE_SUFFIX defined somewhere.
There is a $(CONFIGFILE) you are including, Make finds it but you did not provide the text of it, check if these variables should be defined in there but are not.

Issue while linking GLFW3 precompiled Libs to C++ Project using Makefile

following issue: i'm currently working on some small c++ project, and i use imgui for the user interface. For that to work tho, i also need glfw(3). So i downloaded both the precompiled headers for osx and windows (https://www.glfw.org/download). And i added them to my project.
+---shared
+---lib
\---glfw
+---osx
| libglfw.3.dylib
| libglfw3.a
|
\---win
glfw3.dll
libglfw3.a
libglfw3dll.a
The next step (at least what i tried) was adding the lib .a file in the linkin process after creating the object files from my own sourcecode. I did this by specifying the -Lshared/lib/glfw/$(OS) path as well as the -lglfw3 flag. I did not get an error from those two. But when i run the linker, i get the following error message:
g++ -g -Wall -c -o src/core/src/main.o src/core/src/main.cpp
g++ -g -Wall -Ishared/include -Lshared/lib/glfw/win -lglfw3 -o bin/core src/core/src/main.o
c:/programdata/chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: src/core/src/main.o:C:\Users\REDACTED\Desktop\LS/src/core/src/main.cpp:10: undefined reference to `glfwSetErrorCallback'
collect2.exe: error: ld returned 1 exit status
make: *** [makefile:78: core] Error 1
As far as i understand, this means that the linking of the library was not successfull.
( the code from src/core/src/main.cpp for completeness )
#include <stdio.h>
#include "../../../shared/include/glfw/glfw3.h"
static void glfw_error_callback(int error, const char *description)
{
}
int main(int argc, char *argv[])
{
glfwSetErrorCallback(glfw_error_callback);
printf("Hello World!\n");
return 0;
}
makefile code:
# ------------------------
# --- Global Settings ----
# ------------------------
CC = g++
# --------------------
# --- Common Flags ---
# --------------------
CFLAGS = -g -Wall
LDFLAGS = -I$(INCLUDE)
# Add correct glfw bins for either windows or osx
ifeq ($(OS), Windows_NT)
LDFLAGS += -L$(LIB)/glfw/win
else
LDFLAGS += -L$(LIB)/glfw/osx
endif
LDFLAGS += -lglfw3
# --------------
# --- Paths ----
# --------------
SRC = src
SHARED = shared
INCLUDE = $(SHARED)/include
LIB = $(SHARED)/lib
BIN = bin
DOCS = docs
# ---------------------
# --- Project Paths ---
# ---------------------
pCORE = $(SRC)/core
pIMPORTER = $(SRC)/importer
pEXPORTER = $(SRC)/exporter
pPROCESSOR = $(SRC)/processor
pUNIVERSALCLIENT = $(SRC)/universalclient
# --------------------------
# --- Housekeeping Tasks ---
# --------------------------
clean:
ifeq ($(OS), Windows_NT)
-del /s /q *.o
-rmdir /s /q $(BIN)
else
-find . -type f -name '*.o' -exec rm -f {} \;
-rm -rf $(BIN)
endif
clean_objs:
ifeq ($(OS), Windows_NT)
-del /s /q *.o
else
-find . -type f -name '*.o' -exec rm -f {} \;
-rm -rf $(BIN)
endif
setup:
ifeq ($(OS), Windows_NT)
-mkdir $(BIN)
else
-mkdir -p $(BIN)
endif
# ------------------------------------
# --- Shared Libraries Build Rules ---
# ------------------------------------
# ---------------------------
# --- Project Build Rools ---
# ---------------------------
pCORE_SRC = $(wildcard $(pCORE)/src/*.cpp)
pCORE_OBJ = $(patsubst %.cpp, %.o, $(pCORE_SRC))
core: $(pCORE_OBJ)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(BIN)/core $^
$(pCORE_OBJ): $(pCORE_SRC)
$(CC) $(CFLAGS) -c -o $# $<
i worked myself through many documentations on how to link a library. Does someone understand whats going wrong or could someone explain it to me?
( regarding cmake: please don't ask - i can't use it for this project )

Problem while compiling using a makefile on Cygwin64, why?

I have a problem while compiling my code on Windows (it depends on a huge header only library exprtk), and in particular on msys and Cygwin64 shells. I am trying to compile my code using this makefile:
#====================================================
# OS detection
#====================================================
ifeq ($(OS),Windows_NT)
O_SYSTEM = Windows
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
O_SYSTEM = Linux
else ifeq ($(UNAME_S),Darwin)
O_SYSTEM = MacOS
endif
endif
#====================================================
# VARIABLES
#====================================================
ifeq ($(O_SYSTEM),$(filter $(O_SYSTEM),MacOS Linux))
TARGET_EXEC := examples
TEST_EXEC := tests
else
TARGET_EXEC := examples.exe
TEST_EXEC := tests.exe
endif
LIB := libarsenalgear.a
CC := g++
#====================================================
# FOLDERS
#====================================================
BUILD_DIR := bin
SRC_DIR := src
OBJ_DIR := obj
TEST_DIR := test
LIB_DIR := lib
ifeq ($(O_SYSTEM),Windows)
WIN_INCLUDE := C:\include
WIN_BOOST := C:\boost\include\boost-1_79
endif
#====================================================
# SOURCE FILES
#====================================================
ifeq ($(O_SYSTEM),$(filter $(O_SYSTEM),MacOS Linux))
SRC := $(shell find $(SRC_DIR) -name '*.cpp')
SRC_LIB := $(shell find $(SRC_DIR) -type f | grep -v 'examples.cpp')
TEST := $(shell find $(SRC_DIR) -type f | grep -v 'examples.cpp') $(shell find $(TEST_DIR) -name '*.cpp')
else
SRC := $(wildcard $(SRC_DIR)/*.cpp)
SRC_LIB := $(filter-out $(SRC_DIR)/examples.cpp, $(wildcard $(SRC_DIR)/*.cpp))
TEST := $(filter-out $(SRC_DIR)/examples.cpp, $(wildcard $(SRC_DIR)/*.cpp)) $(wildcard $(TEST_DIR)/*.cpp)
endif
#====================================================
# SOURCE OBJECTS
#====================================================
OBJ := $(SRC:%=$(OBJ_DIR)/%.o)
OBJ_LIB := $(SRC_LIB:%=$(OBJ_DIR)/%.o)
TEST_OBJ := $(TEST:%=$(OBJ_DIR)/%.o)
#====================================================
# DEPENDENCIES AND FLAGS
#====================================================
DEPS := $(OBJ:.o=.d)
ifeq ($(O_SYSTEM),Linux)
INC_DIR := $(shell find $(SRC_DIR) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIR))
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP
else ifeq ($(O_SYSTEM),MacOS)
INC_DIR := $(shell find $(SRC_DIR) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIR)) `pcre-config --cflags`
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP
else
INC_DIR := $(SRC_DIR)
INC_FLAGS := $(addprefix -I,$(INC_DIR)) $(addprefix -I,$(WIN_INCLUDE)) $(addprefix -I,$(WIN_BOOST))
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP
endif
#====================================================
# ALIASES
#====================================================
.PHONY: clean all
#====================================================
# BUILDING
#====================================================
#Building all:
all: $(BUILD_DIR)/$(TARGET_EXEC) $(BUILD_DIR)/$(TEST_EXEC) $(LIB_DIR)/$(LIB)
examples: $(BUILD_DIR)/$(TARGET_EXEC) $(LIB_DIR)/$(LIB)
tests: $(BUILD_DIR)/$(TEST_EXEC) $(LIB_DIR)/$(LIB)
#Building main executable:
$(BUILD_DIR)/$(TARGET_EXEC): $(OBJ)
# mkdir -p $(dir $#)
$(CC) $(OBJ) -o $# $(LDFLAGS)
#Building test executable:
$(BUILD_DIR)/$(TEST_EXEC): $(TEST_OBJ)
# mkdir -p $(dir $#)
$(CC) $(TEST_OBJ) -o $# $(LDFLAGS)
#Put object files into the object dir:
$(OBJ_DIR)/%.cpp.o: %.cpp
# mkdir -p $(dir $#)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
#Create a static library from object files and put it in the library dir:
$(LIB_DIR)/$(LIB): $(OBJ_LIB)
# mkdir -p $(dir $#)
ar rcs $(LIB_DIR)/$(LIB) $(OBJ_LIB)
#====================================================
# CLEAN
#====================================================
clean:
rm -r $(OBJ_DIR) $(BUILD_DIR) $(LIB_DIR)
#====================================================
# INCLUDE
#====================================================
-include $(DEPS)
Which should be a cross-platform makefile. It perfectly works on Ubuntu and MacOS, but on Windows (Cygwin64 and msys) I got the following error:
g++ -std=c++17 -g -Isrc -IC:\include -IC:\Boost\boost_1_79_0 -MMD -MP -c src/examples.cpp -o obj/src/examples.cpp.o
C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (136542)
C:\Users\RUNNER~1\AppData\Local\Temp\cc7rIyrj.s: Assembler messages:
C:\Users\RUNNER~1\AppData\Local\Temp\cc7rIyrj.s: Fatal error: can't write 571 bytes to section .text of obj/src/examples.cpp.o: 'File too big'
C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (136542)
C:\Users\RUNNER~1\AppData\Local\Temp\cc7rIyrj.s: Fatal error: can't close obj/src/examples.cpp.o: File too big
make: *** [Makefile:91: obj/src/examples.cpp.o] Error 1
I am trying to run it on codeql-analysis GitHub workflow.
What do you think?
EDIT
I tried modifing:
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP -Wa,-mbig-obj
and the error is the same.
If I modify instead:
CPPFLAGS := -std=c++17 -g $(INC_FLAGS) -MMD -MP -flto -Wl,-allow-multiple-definition
LDFLAGS := -fuse-linker-plugin
I got same error but the number of "too many sections" is lower (43419):
g++ -std=c++17 -g -Isrc -IC:\include -IC:\boost\include\boost-1_79 -MMD -MP -flto -Wl,-allow-multiple-definition -c src/examples.cpp -o obj/src/examples.cpp.o
C:/MinGW/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (43419)
C:\cygwin64\tmp\ccU7XjRg.s: Assembler messages:
C:\cygwin64\tmp\ccU7XjRg.s: Fatal error: can't write 3975 bytes to section .gnu.lto_.inline.6d3ed2ee of obj/src/examples.cpp.o: 'File too big'
C:/MinGW/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/bin/as.exe: obj/src/examples.cpp.o: too many sections (43419)
C:\cygwin64\tmp\ccU7XjRg.s: Fatal error: can't close obj/src/examples.cpp.o: File too big
make: *** [Makefile:108: obj/src/examples.cpp.o] Error 1
After some hours of tests I've finally found the problem: it was due to the ExprTk library. Since it is a huge header-only library, for a reason that is not clear to me, the Cygwin and MinGW compilers failed to correctly compile it. I solved by simply ignoring this library and all the functions I defined within its objects, by simply adding this preprocessor directive:
#if defined( __linux__ ) || defined( __APPLE__ )
// code which uses ExprTk objects
#endif
In this way the program compiles correctly for Ubuntu, MacOS and Windows, but in the Windows case it ignores the ExprTk objects.

GNU make ifeq comparison not working

I am trying to have a command executed depending on the current target from a list of targets (currently only one entry in that list) before another makefile is executed.
i have this:
$(LIBS):
ifeq ($#,libname)
my command here
endif
$(MAKE) -C ./lib/$#
the problem is, that the ifeq does not get executed even if the target name is correct. Using an $(info $#) shows exactly the libname but the expression is not evaluated as true.
I thought maybe there is a problem with expansion of the automatic variable in a conditional so i tried using an eval like this:
$(LIBS):
$(eval CURRENT_LIB := $#)
ifeq ($(CURRENT_LIB),libname)
my command here
endif
$(MAKE) -C ./lib/$#
info shows that the variable now equals exactly the libname but the ifeq does not get excuted.
When i enter something like ifeq (libname,libname) it works so the statement is working, but the comparison between variable and text does not evaluate to true even if the two are equal and it should work.
GNU make version is 4.1
What am i missing here?
Complete Makefile:
CC := g++
CFLAGS := -v -std=c++0x -pthread -Wall -g -O3
OBJ := mycode.o
OBJ += moreobjects.o
#more objects in here
LIBS = libname
.PHONY: libs $(LIBS)
SRC = $(OBJ:%.o=%.cpp)
DEPFILE := .depend
mytarget: libs $(OBJ)
$(CC) $(CFLAGS) -o $# $(OBJ)
-include $(DEPFILE)
%.o: %.cpp
$(CC) $(CFLAGS) -c $<
$(CC) -MM -std=c++11 $(SRC) > $(DEPFILE)
libs: $(LIBS)
$(LIBS):
$(eval CURRENT_LIB := $#)
ifeq ($(CURRENT_LIB),libname)
./lib/$(CURRENT_LIB)/configure
endif
$(MAKE) -C ./lib/$#
.PHONY: clean_all
clean_all: clean
$(foreach dir,$(LIBS),$(MAKE) clean -C ./lib/$(dir))
.PHONY: clean
clean:
rm -rf mytarget $(OBJ) $(DEPFILE)
Thank You very much!
What you are trying to do cannot work. From the documentation:
Conditionals control what 'make' actually "sees" in the makefile, so they cannot be used to control recipes at the time of execution.
The way I put it is that conditionals are evaluated at the time the Makefile is read. So make reads your Makefile, your conditional is false and it is removed.
"Normal" conditionals, don't work in a recipe with GNU make. Unfortunately that's true.
Workaround:
But you can use Functions for Conditionals and The eval Function instead. A small example for error detection from my build system. Here I use the eval and if function.
Snippet from Makefile.xu, which use eval and if:
xubuild_check_objects:
$(eval RESULT = $(call xu-obj_func-valid,$(xu-src-c-y)))
#echo 'echo nothing (dummy)' >/dev/null
$(if $(filter n,$(RESULT)), \
$(error XUbuild: error: xubuild_check_objects: xu-obj->xu-src-c-y override detected! Cannot build target! Aborting),)
NOTE:
#echo 'echo nothing (dummy)' >/dev/null
This here is required. When no command will be executed after eval, you get a make: Nothing to be done for 'xubuild_check_objects message.
Project Makefile (root directory) with error:
# XUbuild system (MUST included first)
include Makefile.xu
# This produces an error and aborts the build
xu-src-c-y = test.c
all: xubuild_check_objects
Error output:
$ make
Makefile.xu:104: *** XUbuild: error: xubuild_check_objects: xu-obj->xu-src-c-y override detected! Cannot build target! Aborting. Stop.
$
Project Makefile (root directory) without error:
# XUbuild system (MUST included first)
include Makefile.xu
# My build system is happy with this:
xu-src-c-y += test.c
all: xubuild_check_objects
Output (no error):
$ make
$
The full error detection from my build system simplified. I removed the most Makefile.xu "code" and only post the error detection here. (I don't explain my whole build system in this answer):
# XUbuild generic object
xu-obj := :xu-obj
xu-obj_del := :
# XUbuild object types
xu-obj_nop := n
xu-obj_yes := y
xu-obj_module := m
xu-obj_src := s
xu-obj_flag := f
# XUbuild source priority
xu-obj_src_head := 0
xu-obj_src_normal := 1
# XUbuild source types
xu-obj_src_a := 0
xu-obj_src_c := 1
xu-obj_src_cpp := 2
# XUbuild object functions
xu-obj_func-get = $(filter $(xu-obj)%,$(1))
xu-obj_func-remove = $(filter-out $(xu-obj)%,$(1))
xu-obj_func-valid = $(if $(call xu-obj_func-get,$(1)),y,n)
# XUbuild source objects
xu-src := $(xu-obj)$(xu-obj_del)
# XUbuild C source
xu-src-c := $(xu-src)$(xu-obj_src_normal)$(xu-obj_del)$(xu-obj_src_c)$(xu-obj_del)
xu-src-c- := $(xu-src-c)$(xu-obj_nop)
xu-src-c-y := $(xu-src-c)$(xu-obj_yes)
XUBUILD_PHONY += xubuild_check_objects
xubuild_check_objects:
$(eval RESULT = $(call xu-obj_func-valid,$(xu-src-c-y)))
#echo 'echo nothing (dummy)' >/dev/null
$(if $(filter n,$(RESULT)), \
$(error XUbuild: error: xubuild_check_objects: xu-obj->xu-src-c-y override detected! Cannot build target! Aborting),)
.PHONY: $(XUBUILD_PHONY)

undefined reference to `main' with makefile on linux, with boost and mpi

I am not very familiar with make; i've always used and modified this highly ancient makefile I inherited from another project, modifying it as necessary. Up until now, it has functioned perfectly, compiling together projects with 20-50 files, even within sub-directories, determining and building all the dependencies properly.
Today I am running a very simple test code to determine if BOOST.MPI will work on a cluster I recently got access to. I am trying to compile a 1-file test case to make sure that the library works. This is also my first time building and linking to boost on this system.
I have boost installed in my user directory: ~/boost, and I've run the appropriate bjam to ensure that BOOST.MPI is present. I don't believe my problem lies there. As you'll see in a moment, however, I had to include -lboost_mpi and -lboost_serialization to get as far as I did.
The makefile seems to compile, and assemble just fine producing the intermediary .a file. It hangs up on the linking step with a surprising error:
Creating dependency for "boosttest.cpp"
Compiling "boosttest.cpp"
Assembling ag...
ar: creating ./libag.a
Linking bt1...
/usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
make: *** [bt1] Error 1
The only source code I've written (copy/pasted right out of the Boost.MPI implementation page):
boosttest.cpp:
#include <boost/mpi/environment.hpp>
#include <boost/mpi/communicator.hpp>
#include <iostream>
int main(int argc, char* argv[])
{
boost::mpi::environment env(argc, argv);
boost::mpi::communicator world;
std::cout << "I am process " << world.rank() << " of " << world.size()<< "." << std::endl;
return 0;
}
Now for the part where I get lost. This is the makefile I've modified. I mostly understand what parts of it are doing, and it is the only makefile I've ever seen (although as mentioned I'm not very experienced with them) to produce .d files containing a list of all dependent libraries.
Makefile:
PROJECT = boosttest
# The names of the sub-projects that the executable depends on. These names are used later on to define targets, location, libraries, etc.
DEPS =
# The names of the sub-projects that the test executable depends on.
TEST_DEPS =
EXE_DEPS =
LOCAL_O_FILES = boosttest.o
LOCAL_TEST_O_FILES =
LOCAL_LIB_NAME = ag
LOCAL_LIB_DIR = .
LOCAL_TEST_LIB_NAME =
LOCAL_TEST_LIB_DIR =
LOCAL_INCLUDE_ROOT = .
EXE_NAME = BT
MPIC_DIR = /usr/local/mvapich2-1.6-gcc/
#these assume our local path and bin are set up properly since I don't know where the compilers are
CC = $(MPIC_DIR)/bin/mpicc
CCC = $(MPIC_DIR)/bin/mpicxx
F77 = $(MPIC_DIR)/bin/mpif77
CLINKER = $(MPIC_DIR)/bin/mpicc
CCLINKER = $(MPIC_DIR)/bin/mpicxx
FLINKER = $(MPIC_DIR)/bin/mpif90
F90 = $(MPIC_DIR)/bin/mpif90
F90LINKER = $(MPIC_DIR)/bin/mpif90
MAKE = make --no-print-directory
SHELL = /bin/sh
#PROF = -ggdb -O2
PROF = -O2
ADDITIONAL_LIBS = -lboost_mpi -lboost_serialization
SED = $(shell which sed)
GREP = $(shell which grep)
# Warnings will depend on the GCC version -- if it's 4, have "-Wdeclaration-after-statement -Wunused-value -Wunused-variable"
#GCC_MAJOR_VERSION = $(shell $(CCC) --version | $(GREP) "\(egcs\|gcc\)" | $(SED) "s/[^0-9]*\([0-9]\).*/\1/")
#WARNINGS = -Wno-import $(shell if test $(GCC_MAJOR_VERSION) -eq 4; then echo -Wunused-value -Wunused-variable; fi)
#GCC_INSTALL_DIR = /turing/software-linux/mpich-eth
GCC_INSTALL_DIR = $(MPIC_DIR)
GCC_INCLUDE_DIR = $(GCC_INSTALL_DIR)/include/
GCC_LIB_DIR = $(GCC_INSTALL_DIR)/lib/
BOOST_DIR = ~/boost
BOOST_LIB_DIR = ~/boost/stage/lib
# Expand SRCDIR so that it turns into "-I <srcdir>" for each listed directory
INCLUDE_DIRS = -I $(OBJC_ROOT)/include $(foreach dep, $(UNIQUE_DEPS), -I$($(dep)_INCLUDE_ROOT)) -I $(LOCAL_INCLUDE_ROOT) -I $(BOOST_DIR) -I $(GCC_INCLUDE_DIR)
#C_FLAGS = -DROM $(PROF) $(WARNINGS) $(INCLUDE_DIRS)
C_FLAGS = -DROM $(PROF) $(INCLUDE_DIRS)
L_FLAGS = $(foreach dir, $(OBJC_ROOT) $(DEP_LIB_DIRS), -L$(dir)) -L $(BOOST_LIB_DIR) -L $(GCC_LIB_DIR) $(PROF) $(ADDITIONAL_LIBS)
TEST_L_FLAGS = $(foreach dir, $(OBJC_ROOT) $(TEST_DEP_LIB_DIRS), -L$(dir)) -L/usr/lib -Xlinker --whole-archive $(TEST_REQUIRED_LIBS) -Xlinker --no-whole-archive
REQUIRED_LIBS = $(foreach dep, $(DEPS) LOCAL, $(if $($(dep)_LIB_NAME), -l$($(dep)_LIB_NAME)))
TEST_REQUIRED_LIBS = $(foreach dep, $(TEST_DEPS) LOCAL LOCAL_TEST, $(if $($(dep)_LIB_NAME), -l$($(dep)_LIB_NAME)))
.SUFFIXES:
.SUFFIXES: .d .cc .cpp .c .o
ASSEMBLE_TARGETS = $(foreach dep,$(DEPS),$(dep)_LIB_NAME)
ASSEMBLE_TEST_TARGETS = $(foreach dep,$(TEST_DEPS),$(dep)_LIB_NAME)
CLEAN_TARGETS = $(foreach dep, $(UNIQUE_DEPS), $(dep)_CLEAN)
LOCAL_D_FILES = $(LOCAL_O_FILES:.o=.d)
LOCAL_TEST_D_FILES = $(LOCAL_TEST_O_FILES:.o=.d) $(TEST_RUNNER:.o=.d)
DEP_LIB_DIRS = $(foreach dep, $(DEPS) LOCAL, $($(dep)_LIB_DIR))
TEST_DEP_LIB_DIRS = $(foreach dep, $(TEST_DEPS) LOCAL LOCAL_TEST, $($(dep)_LIB_DIR))
UNIQUE_ASSEMBLE_TARGETS = $(sort $(ASSEMBLE_TARGETS) $(ASSEMBLE_TEST_TARGETS))
UNIQUE_DEPS = $(sort $(DEPS) $(TEST_DEPS))
LOCAL_LIB = $(if $(LOCAL_LIB_NAME), $(LOCAL_LIB_DIR)/lib$(LOCAL_LIB_NAME).a)
LOCAL_TEST_LIB = $(if $(LOCAL_TEST_LIB_NAME), $(LOCAL_TEST_LIB_DIR)/lib$(LOCAL_TEST_LIB_NAME).a)
EXE_TARGETS = $(foreach dep,$(EXE_DEPS),$(dep)_EXE_NAME)
INSTALL_TARGETS = $(foreach dep,$(EXE_DEPS),$(dep)_INSTALL)
export PROJECTS += $(PROJECT)
# PHONY targets get remade even if there exists an up-to-date file with the same name.
.PHONY: default clean compile assemble link submit
# Targets for mortals
default: link
clean: $(CLEAN_TARGETS) LOCAL_CLEAN
compile: $(DEPS) $(LOCAL_D_FILES) $(LOCAL_O_FILES)
assemble: compile $(ASSEMBLE_TARGETS) $(LOCAL_LIB)
link: assemble $(EXE_TARGETS) $(EXE_NAME)
install: $(INSTALL_TARGETS) $(if $(EXE_NAME), LOCAL_INSTALL)
submit: link
qsub $(PROJECT).qsub
# Targets for make
# Invoking sub projects
$(UNIQUE_DEPS): MAKE_TARGET = $(if $(filter %_TEST, $#), compile-tests, compile)
$(UNIQUE_DEPS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($#_DIR) && $(MAKE) $(MAKE_TARGET))
# First, remove the _LIB_NAME attached by ASSEMBLE_TARGETS, a
$(UNIQUE_ASSEMBLE_TARGETS): DEP_NAME = $(#:_LIB_NAME=)
$(UNIQUE_ASSEMBLE_TARGETS): MAKE_TARGET = $(if $(filter %_TEST, $(DEP_NAME)), assemble-tests, assemble)
$(UNIQUE_ASSEMBLE_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) $(MAKE_TARGET))
# First, remove the _EXE_NAME attached by EXE_TARGETS, a
$(EXE_TARGETS): DEP_NAME = $(#:_EXE_NAME=)
$(EXE_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) link)
$(CLEAN_TARGETS): DEP_NAME = $(#:_CLEAN=)
$(CLEAN_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) clean)
$(INSTALL_TARGETS): DEP_NAME = $(#:_INSTALL=)
$(INSTALL_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) install)
#Local stuff
# The rule to change either a '.c' or a '.m' to a '.o'
#%.o : %.c %.d %.cc %.cpp
.cc.o .cpp.o .c.o:
#echo "Compiling \"$<\""
#$(CCC) -c $(C_FLAGS) $< -o $#
.cc.d .cpp.d .c.d :
#echo "Creating dependency for \"$<\""
# #$(CCC) $(WARNINGS) $(INCLUDE_DIRS) -MM $< -o $#
# This foogly hack because gcc seems to have issues with emitting the correct target/dependency names of
# files in sub-dirs of the current dir (specifically, it doesn't add the sub-dir to the target
# name, and insists on adding the directory to the dependencies) which ends up breaking dependencies...)
#dependLine=$$( $(CCC) $(C_FLAGS) $(INCLUDE_DIRS) -MM $< ); \
dirName=$$( dirname $< | $(SED) "s/\//\\\\\//g" ); \
dependLine=$$( echo $${dependLine} | $(SED) "s/ $${dirName}\// /g" ); \
oFile=$$( echo $${dependLine} | $(SED) "s/:.*//" ); \
dependencies=$$( echo $${dependLine} | $(SED) "s/.*://" ); \
echo $${oFile} $${oFile%.o}.d: $${dependencies} | $(SED) "s/ \\\//g" > $#
$(UNIQUE_ASSEMBLE_TARGETS): DEP_NAME = $(#:_LIB_NAME=)
$(UNIQUE_ASSEMBLE_TARGETS): MAKE_TARGET = $(if $(filter %_TEST, $(DEP_NAME)), assemble-tests, assemble)
$(UNIQUE_ASSEMBLE_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) $(MAKE_TARGET))
# First, remove the _EXE_NAME attached by EXE_TARGETS, a
$(EXE_TARGETS): DEP_NAME = $(#:_EXE_NAME=)
$(EXE_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) link)
$(CLEAN_TARGETS): DEP_NAME = $(#:_CLEAN=)
$(CLEAN_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) clean)
$(INSTALL_TARGETS): DEP_NAME = $(#:_INSTALL=)
$(INSTALL_TARGETS):
$(if $(findstring $(DEP_NAME), $(PROJECTS)),,cd $($(DEP_NAME)_DIR) && $(MAKE) install)
#Local stuff
# The rule to change either a '.c' or a '.m' to a '.o'
#%.o : %.c %.d %.cc %.cpp
.cc.o .cpp.o .c.o:
#echo "Compiling \"$<\""
#$(CCC) -c $(C_FLAGS) $< -o $#
.cc.d .cpp.d .c.d :
#echo "Creating dependency for \"$<\""
# #$(CCC) $(WARNINGS) $(INCLUDE_DIRS) -MM $< -o $#
# This foogly hack because gcc seems to have issues with emitting the correct target/dependency names of
# files in sub-dirs of the current dir (specifically, it doesn't add the sub-dir to the target
# name, and insists on adding the directory to the dependencies) which ends up breaking dependencies...)
#dependLine=$$( $(CCC) $(C_FLAGS) $(INCLUDE_DIRS) -MM $< ); \
dirName=$$( dirname $< | $(SED) "s/\//\\\\\//g" ); \
dependLine=$$( echo $${dependLine} | $(SED) "s/ $${dirName}\// /g" ); \
oFile=$$( echo $${dependLine} | $(SED) "s/:.*//" ); \
dependencies=$$( echo $${dependLine} | $(SED) "s/.*://" ); \
echo $${oFile} $${oFile%.o}.d: $${dependencies} | $(SED) "s/ \\\//g" > $#
$(LOCAL_LIB): compile $(ASSEMBLE_TARGETS)
#echo Assembling $(LOCAL_LIB_NAME)...
#ar rs $(LOCAL_LIB) $(LOCAL_O_FILES)
# Create the executable
$(EXE_NAME): assemble
#echo Linking $(EXE_NAME)...
#$(CCC) -o $(EXE_NAME) $(L_FLAGS)
# Erase all object files, the dependencies file, the core file and the executable, then rebuild everything
LOCAL_CLEAN:
#echo Cleaning $(PROJECT)...
#rm -f $(LOCAL_O_FILES) $(LOCAL_TEST_O_FILES) $(LOCAL_LIB) $(LOCAL_TEST_LIB) $(EXE_NAME) $(TEST_EXE_NAME) $(LOCAL_D_FILES) $(LOCAL_TEST_D_FILES) $(TEST_RUNNER) $(TEST_RUNNER:.o=.d) core*
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
-include $(LOCAL_O_FILES:.o=.d) $(LOCAL_TEST_O_FILES:.o=.d)
endif
The paths to my mpicxx compiler (needed for the cluster, and for those unfamiliar, it wraps gcc) are correct, as evidenced by the fact that it does compile, it just won't link. Similarly, my boost library paths seem functional, the -lboost_mpi flag gets caught properly.
At this point, my question has extended to be for my own education based on how this makefile works/intends to work. Ultimately the entirely obvious/simple command:
mpicxx boosttest.cpp -L ~/boost/stage/lib/ -lboost_mpi -lboost_serialization -o test
however I want to get a proper makefile going as once I get past this test case verifying Boost.MPI's equivalent of a hello world, I'll be moving on to projects involving my full source code, 20+ files with cross dependencies, etc. Any help or intuition would be greatly appreciated.
Based on the suggestion of #Oktalist above, I was able to find something that works, at least for the single-file case, but I can't see why it won't work when I extend this to multiple files. I'm still at a loss why this worked in the past but not now, but perhaps I changed something I wasn't tracking.
The correction is near the end, in this block:
# Create the executable
$(EXE_NAME): assemble
#echo Linking $(EXE_NAME)...
#$(CCC) $(L_FLAGS) $(LOCAL_LIB) -o $(EXE_NAME)