| [ Return to Bugs & Features | SVN ⇄ GIT ]
STR #3315
Application: | FLTK Library |
Status: | 1 - Closed w/Resolution |
Priority: | 3 - Moderate, e.g. unable to compile the software |
Scope: | 2 - Specific to an operating system |
Subsystem: | Build Files |
Summary: | makefile build broken under NetBSD |
Version: | 1.4-feature |
Created By: | manolo |
Assigned To: | manolo |
Fix Version: | 1.4-feature (SVN: v11872) |
Update Notification: | |
Trouble Report Files:
No files
Trouble Report Comments:
|
#1 | manolo 08:09 Jun 10, 2016 |
| File src/Makefile uses this construct CPPFILES += $(shell if test $(BUILD_X11) = Yes -a $(BUILD_XFT) = Yes; then echo $(XLIBXFTFILES); fi) which does not work with NetBSD make.
It does work when gmake instead of make is used.
This construct has been introduced in 1.3.4 and is not used in 1.3.3 | |
|
#2 | AlbrechtS 10:49 Jun 10, 2016 |
| Hi Manolo,
isn't this (XLIBXFTFILES) only used in the porting branch, i.e. 1.4.0 (or, since we don't have this version yet, "1.4-feature")?
In 1.3.4 (as of svn r 11768) I can only see:
$ grep shell src/Makefile MMFILES = $(shell if test $(USEMMFILES) = Yes; then echo $(OBJCPPFILES); fi)
Well, this is similar to the statement you mentioned, but this has been there for a long time (at least since 2010-12-17, svn r 8051).
Two questions:
(1) Does the issue also concern branch-1.3 (i.e. 1.3.4) ? (2) What is the error message? | |
|
#3 | manolo 22:29 Jun 10, 2016 |
| Yes, this post concerns only the porting branch (so, there's no urgency to fix that), and the problem occurs with NetBSD only.
What happens is that the test performed by the construct is always negative under NetBSD. Thus, the test aiming at adding to the list of c++ source files those specific of X11 or X11+Xft do not add any file under NetBSD, and the build aborts at the first link because many symbols are absent from libfltk.
Under NetBSD, if gmake (instead of make) is used, the build is OK.
I discovered after writing the STR that there's a similar construct in the main branch too. But it is meaningful only for Mac OS X. A negative test result is OK for any Linux/Unix platform.
In the main branch, there's no platform variation of the list of source files to be compiled. The variation is created by #include statements within source files themselves controlled by #if / #else / #endif directives. One exception, as said above, is for objective-c++ files on Mac OS X.
In a nutshell, the problem is how to create platform variation in source file lists in a cross-platfom way for the make-based build.
CMake-based build is OK under NetBSD (so CMake has solved this problem). | |
|
#4 | manolo 00:28 Jun 16, 2016 |
| More about "how to create platform variation in source file lists in a cross-platfom way":
The problem is that the construct CPPFILES += $(shell if test $(BUILD_X11) = Yes; \ then echo $(XLIBCPPFILES); fi) does not work on FreeBSD and NetBSD.
This blog post http://gallium.inria.fr/blog/portable-conditionals-in-makefiles/ explains this is a classic dilemma and proposes 2 solutions. I propose here an implementation of the first solution, based on substitution.
This simple Makefile allows to test the 4 combinations of positive/negative values for BUILD_X11 and BUILD_XFT.
In this implementation, positive is _Yes_ and negative is _No_. Experience shows that Yes/No does not work, and that yes/no could work but would fail if substring "no" occurs in a filename. _true_/_false_ works also, but true/false do not.
It has been tested OK on Darwin, FreeBSD and NetBSD.
===================== Makefile ==================
CPPFILES='always.cxx' XLIBCPPFILES=for_X11.cxx XLIBXFTFILES=for_Xft.cxx XLIBFONTFILES=X11_without_Xft.cxx
BUILD_X11=_Yes_ # change this value BUILD_XFT=_No_ # change this value
#CPPFILES += $(shell if test $(BUILD_X11) = Yes; then echo $(XLIBCPPFILES); fi) XLIBCPPFILES := $(BUILD_X11:_Yes_=$(XLIBCPPFILES)) XLIBCPPFILES := $(XLIBCPPFILES:_No_=) CPPFILES += $(XLIBCPPFILES)
#CPPFILES += $(shell if test $(BUILD_X11) = Yes -a $(BUILD_XFT) = Yes; then echo $(XLIBXFTFILES); fi) TMP_XFT := $(BUILD_X11:_Yes_=$(BUILD_XFT)) XLIBXFTFILES := $(TMP_XFT:_Yes_=$(XLIBXFTFILES)) XLIBXFTFILES := $(XLIBXFTFILES:_No_=) CPPFILES += $(XLIBXFTFILES)
#CPPFILES += $(shell if test $(BUILD_X11) = Yes -a $(BUILD_XFT) != Yes; then echo $(XLIBFONTFILES); fi) TMP_FONT := $(BUILD_X11:_No_=_empty_) TMP_FONT := $(TMP_FONT:_Yes_=$(BUILD_XFT)) XLIBFONTFILES := $(TMP_FONT:_No_=$(XLIBFONTFILES)) XLIBFONTFILES := $(XLIBFONTFILES:_Yes_=) XLIBFONTFILES := $(XLIBFONTFILES:_empty_=) CPPFILES += $(XLIBFONTFILES)
.SILENT:
all: echo 'CPPFILES='$(CPPFILES)
=================================================
Thus, this is a solution, but rather hackish. It would fail is any of substrings "_Yes_", "_No_" or "_empty_" occurs in platform-specific filenames.
Many other blogs conclude complex portable makefiles just do not exist, and suggest to use a portable make program, that is, gmake. | |
|
#5 | AlbrechtS 09:01 Aug 06, 2016 |
| Note: modified Software Version to 1.4-feature.
I propose to change configure slightly and use solution 2 (indirection) from the blog post cited above. If this works on *BSD then I believe that this solution is much clearer and shorter, hence much better maintainable. This would also be true if we added even more build variations.
Side note: I can read this Makefile (see below) and understand it w/o knowing
(1) configure should be changed to set only one variable (BUILD) instead of BUILD_X11, BUILD_XFT etc.. This variable could also be called PLATFORM, but I used BUILD in my tests. BUILD would be one of:
WIN: Windows (GDI) OSX: Mac OS X X11: X11 without Xft XFT: X11 with Xft more to come, if needed.
(2) With these changes in place (not implemented yet, but should be easy to do), the (test) Makefile could be:
# ===================== Makefile ==================
# assume configure was changed to set only one variable: # BUILD = {WIN|X11|XFT|OSX} # X11 means: X11 w/o Xft # XFT means: X11 with Xft
# change this or run with "BUILD=value make" # BUILD=OSX # change this value to one of {WIN|X11|XFT|OSX}
# used always, no matter what BUILD is CPPFILES = always.cxx
# used for Windows CPPFILES_WIN = Win32.cxx
# used for Mac OS (BUILD=OSX) CPPFILES_OSX = Mac.cxx
# used for X11 always (BUILD=X11 _or_ BUILD=XFT) CPPFILES_X = X11_always.cxx
# used for X11 w/o Xft (BUILD=X11) CPPFILES_X11 = $(CPPFILES_X) X11.cxx
# used for X11 with Xft (BUILD=XFT) CPPFILES_XFT = $(CPPFILES_X) Xft.cxx
# add BUILD-specific files to CPPFILES CPPFILES += $(CPPFILES_$(BUILD))
.SILENT:
all: echo 'CPPFILES='$(CPPFILES)
# =================================================
To test, cut'n'paste these four lines:
BUILD=WIN make BUILD=OSX make BUILD=X11 make BUILD=XFT make
My test results on Windows and Linux:
$ BUILD=WIN make CPPFILES=always.cxx Win32.cxx $ BUILD=OSX make CPPFILES=always.cxx Mac.cxx $ BUILD=X11 make CPPFILES=always.cxx X11_always.cxx X11.cxx $ BUILD=XFT make CPPFILES=always.cxx X11_always.cxx Xft.cxx
Manolo, can you please test on *BSD and Mac OS ? What do you think? | |
|
#6 | AlbrechtS 09:04 Aug 06, 2016 |
| Sorry, that incomplete sentence should read:
Side note: I can read this Makefile (see below) and understand it w/o knowing this special substitution syntax. | |
|
#7 | manolo 09:36 Aug 08, 2016 |
| The makefile given at #5 above Runs OK under FreeBSD Using Cppfiles += $(cppfiles_$(build)) Seems an excellent idea. | |
|
#8 | manolo 01:39 Aug 09, 2016 |
| The makefile given at #5 above runs OK also under NetBSD. | |
|
#9 | AlbrechtS 15:14 Aug 11, 2016 |
| Okay, I think we need two or maybe three such variables then, because we have system and graphics drivers and maybe more (OpenGL?). Changes would be in configure.in and Makefile(s), but that should be it.
Would you like me to take a stab on it, or would you like to do it yourself? | |
|
#10 | manolo 02:02 Aug 12, 2016 |
| Ok I'll do it | |
|
#11 | manolo 10:45 Aug 12, 2016 |
| With r11872, configure build runs OK on NetBSD, FreeBSD, Ubuntu, MSWindows10, Mac OS X.
Thanks to Albrecht for finding the solution. | |
|
#12 | manolo 10:48 Aug 12, 2016 |
| Fixed in Subversion repository. | |
|
#13 | AlbrechtS 06:58 Aug 13, 2016 |
| Manolo wrote: > Thanks to Albrecht for finding the solution.
Thanks to you, Manolo, for finding and reporting the bug, researching, finding a potential solution in the 'net, proposing a solution with a small test case, and finally implementing the solution.
My part was tiny compared with that. | |
[ Return to Bugs & Features ]
|
| |