dmake target specific variables - dmake

This topic has been discussed a few times, but the answers only seem to cover GNU make. For this particular Makefile, I'd like it to be a single cross-platform file assuming GNU make for Mac and Linux, and dmake for Windows.
I'm trying to figure out how to assign macros/variables for only a specified target using dmake.
In this case, I'm going to use it for preprocessor definitions.
I'd like to add
CPPFLAGS += -DINITIAL
to an 'initial' target and
CPPFLAGS += -DUPDATE
to an 'update' target.
Using GNU make, we can achieve this by the following:
initial: CPPFLAGS += -DINITIAL
initial:
...
update: CPPFLAGS += -DUPDATE
update:
...
but unfortunately, it breaks the build using dmake.

Using dmake, the syntax needs to be slightly changed to
initial ?= CPPFLAGS += -DINITIAL
Resource: http://www.openoffice.org/tools/dmake/dmake_4.3.html#lbAS
Wrapping the different syntaxes in OS checks allows for a cohesive Makefile .

Related

QMake 5.15 don't understand wildcard adding files [duplicate]

I have a .pro file which looks like:
SOURCES += myfolder/source1.cpp \
myfolder/source2.cpp
HEADERS += myfolder/header1.h\
myfolder/header2.h
FORMS += myfolder/form1.ui\
myfolder/form2.ui
And everything works great. However, if I try to use an asterisk to include all the files, i.e.:
SOURCES += myfolder/*.cpp
HEADERS += myfolder/*.h
FORMS += myfolder/*.ui
qmake throws a file-not-found-error:
WARNING: Failure to find: myfolder\*.cpp
[...]
:-1: error: No rule to make target `myfolder/*.cpp', needed by `release/source1.o'. Stop.
In both cases, Qt-Creator can find the files.
Is there a way to use the asterisk? It's annoying to type the files manually.
Thank you!
[EDIT: Qt 4.8.4, Windows 7, Qt-Creator 2.6.1. Sry for forgetting this thought it isnt needed.]
[EDIT: Found solution: http://qt-project.org/forums/viewthread/1127 . Thank you anyway!]
In qmake 3.0, at least, it's possible to use something like:
SOURCES = $$files(*.cpp, true)
HEADERS = $$files(*.h, true)
The true argument will cause the files function to recursively find all files matching the pattern given by the first argument.
At first, using asterisk is bad practice - despite that qmake allows it, QtCreator cannot edit such *.pro correctly on adding new, renaming or deleting file. So try to add new files with "New file" or "Add existing files" dialogs.
QMake has for loop and function $$files(directory_path: String). Also append files to SOURCES or HEADERS variable respectively.
Brief example, which adds all files, but not directories, to variable FILES (not affect build or project tree):
files = $$files($$PWD/src)
win32:files ~= s|\\\\|/|g
for(file, files):!exists($$file/*):FILES += $$file
If you want to check if file is *.cpp, try to use contains($$file, ".cpp").
files = $$files($$PWD/src)
win32:files ~= s|\\\\|/|g
for(file, files):!exists($$file/*):contains($$file, ".cpp"):SOURCES += $$file

Add an extension in a .pro variable

I'm trying to print a message with QMake but I have problems with extensions:
lib_name = $$1
message("test1: $$MYPATH/$$lib_name/src/$$lib_name.pri");
message("test2: $$MYPATH/$$lib_name/src/$$lib_name");
For some reason, test1 doesn't print the correct path. It just prints the path until src/. But, test2 is ok. It prints everything until the value in $$1.
Any workaround?
QMake supports variables (objects) with members that can be used using the dot . operator e.g. target.path for INSTALLS. So, in your case, $$lib_name.pri means that you're accessing the member pri of lib_name which doesn't exist so there's no output.
You need to enclose variables in curly braces for QMake to distinguish them from the surrounding text i.e. $${lib_name}.pri.
Example:
message("test1: $$MYPATH/$$lib_name/src/$${lib_name}.pri");
# ~~~~~~~~~~~~
For more examples of objects, see Adding Custom Target and Adding Compilers sections of QMake's Advanced Usage page.
Here's another relevant SO thread: QMake - How to add and use a variable into the .pro file

how to define a config in pro file?

how to define a config in pro file ?
by default, we have two config, debug and release. I want to add 2 other config but not in pro.user ! in pro file.
Your question is a bit unclear. It sounds like maybe you're currently building with "debug" and "release", from the command line, and you want to add your own build variants similar to that.
If that's the case... the mechanism for this is addExclusiveBuilds. Here is an example. I wouldn't recommend to mess around with it if you aren't comfortable reading qmake code.
TEMPLATE = app
SOURCES = main.cpp
# Adds two build variants.
# One of them builds the app with optimal compiler flags,
# the other one builds the app with support for collecting coverage data.
# For the first one, CONFIG will contain `optimized' and a Makefile.Optimized will be generated.
# For the second, CONFIG will contain `coverage' and a Makefile.Coverage will be generated.
# There will also be a top-level Makefile which invokes both the sub-makefiles.
addExclusiveBuilds(optimized, Optimized, coverage, Coverage)
CONFIG(optimized, coverage|optimized) {
message(I am in the optimized build variant)
QMAKE_CXXFLAGS += -O3
TARGET = myapp-optimized
}
else:CONFIG(coverage, coverage|optimized) {
message(I am in the coverage build variant)
QMAKE_CXXFLAGS += --coverage
QMAKE_LFLAGS += --coverage
TARGET = myapp-coverage
}
else {
message(I am in the glue project which contains the build variants)
# This will cause a `make' to build both optimized and coverage
# variants by default.
CONFIG += build_all
}
If I understand what you are saying, you add what you want to the CONFIG variable:
CONFIG += user_setting
...
user_setting: message( "compiling with user_setting" )
See the qmake manual where it talks about the CONFIG variable, especially near the end of the section.

CMake, Qt, gcc and precompiled headers

I'm (once again) struggling with the creation of precompiled headers in conjunction with gcc and Qt on the Apple platform.
When now creating my precompiled header I use a code section (based on good old "PCHSupport_26.cmake") to extract the compile flags as follows:
STRING(TOUPPER "CMAKE_CXX_FLAGS_${CMAKE_BUILD_TYPE}" _flags_var_name)
SET(_args ${CMAKE_CXX_FLAGS} ${${_flags_var_name}})
GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES )
FOREACH(_item ${DIRINC})
LIST(APPEND _args "-I${_item}")
ENDFOREACH(_item)
GET_DIRECTORY_PROPERTY(_defines_global COMPILE_DEFINITIONS)
LIST(APPEND defines ${_defines_global})
STRING(TOUPPER "COMPILE_DEFINITIONS_${CMAKE_BUILD_TYPE}" _defines_for_build_name) GET_DIRECTORY_PROPERTY(defines_build ${_defines_for_build_name})
LIST(APPEND _defines ${_defines_build})
FOREACH(_item ${_defines})
LIST(APPEND _args "-D${_item}")
ENDFOREACH(_item ${_defines})
LIST(APPEND _args -c ${CMAKE_CURRENT_SOURCE_DIR}/${PRECOMPILED_HEADER} -o ${_gch_filename})
SEPARATE_ARGUMENTS(_args)
Unfortunately the above compiler flags miss two important parameter that CMake does generate when using the build-in compiler rules:
-DQT_DEBUG
and when compiling with the generated precompiled header, I get errors as follows:
file.h: not used because QT_DEBUG is defined.
I would need your help with the following:
Is the above way to retrieve the compiler flags correct ?
Is there a better, easier, simpler way to do this ?
Why does -DQT_DEBUG not show up in COMPILE_DEFINITIONS or COMPILE_DEFINITIONS_${CMAKE_BUILD_TYPE}
If you are using XCode simply:
SET_TARGET_PROPERTIES(${target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER YES)
SET_TARGET_PROPERTIES(${target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${target}/std.h")
I'm trying myself to use precompiled headers with raw gcc on linux through CMake but I haven't still figured it out. It look like it's working but I don't see any speed improvements.
Edit:
I managed to use pch in gcc finally with the macro you can find here: http://www.mail-archive.com/cmake#cmake.org/msg04394.html

how to compile MPI and non-MPI version of the same program with automake?

I have a C++ code that can be compiled with MPI support depending on a
certain preprocessor flag; missing the appropriate flag, the sources
compile to a non-parallel version.
I would like to setup the Makefile.am so that it compiles both the
MPI-parallel and the sequential version, if an option to
./configure is given.
Here's the catch: MPI has its own C++ compiler wrapper, and insists
that sources are compiled and linked using it rather than the standard
C++ compiler. If I were to write the Makefile myself, I would have to
do something like this:
myprog.seq: myprog.cxx
$(CXX) ... myprog.cxx
myprog.mpi: myprog.cxx
$(MPICXX) -DWITH_MPI ... myprog.cxx
Is there a way to tell automake that it has to use $(MPICXX) instead
of $(CXX) when compiling the MPI-enabled version of the program?
I have the same problem, and I've found that there's no really good way to get autotools to conditionally use MPI compilers for particular targets. Autotools is good at figuring out which compiler to use based on what language your source is written in (CC, CXX, FC, F77, etc.), but it really isn't good at figuring out whether or not to use MPI compiler for a particular target. You can set MPICC, MPICXX, etc., but you essentially have to rewrite all your Makefile rules for your target (as you've done above) if you use the compiler this way. If you do that, what's the point of writing an automake file?
Someone else suggested using MPI like an external library, and this is the approach I'd advocate, but you shouldn't do it by hand, because different MPI installations have different sets of flags they pass to the compiler, and they can depend on the language you're compiling.
The good thing is that all the currently shipping MPI compilers that I know of support introspection arguments, like -show, -show-compile or -show-link. You can automatically extract the arguments from the scripts.
So, what I did to deal with this was to make an m4 script that extracts the defines, includes, library paths, libs, and linker flags from the MPI compilers, then assigns them to variables you can use in your Makefile.am. Here's the script:
lx_find_mpi.m4
This makes MPI work the way automake expects it to. Incidentally, this is the approach CMake uses in their FindMPI module, and I find it works quite well there. It makes the build much more convenient because you can just do something like this for your targets:
bin_PROGRAMS = mpi_exe seq_exe
# This is all you need for a sequential program
seq_exe_SOURCES = seq_exe.C
# For an MPI program you need special LDFLAGS and INCLUDES
mpi_exe_SOURCES = mpi_exe.C
mpi_exe_LDFLAGS = $(MPI_CXXLDFLAGS)
INCLUDES = $(MPI_CXXFLAGS)
There are similar flags for the other languages since, like I said, the particular flags and libraries can vary depending on which language's MPI compiler you use.
lx_find_mpi.m4 also sets some shell variables so that you can test in your configure.ac file whether MPI was found. e.g., if you are looking for MPI C++ support, you can test $have_CXX_mpi to see if the macro found it.
I've tested this macro with mvapich and OpenMPI, as well as the custom MPICH2 implementation on BlueGene machines (though it does not address all the cross-compiling issues you'll see there). Let me know if something doesn't work. I'd like to keep the macro as robust as possible.
I am sorry that having automake use MPI is so difficult. I have been struggling with this for many months trying to find a good solution. I have a source tree that have one library and then many programs in sub-folders that use the library. Some of the folders are mpi programs, but when I try to replace CXX with the MPI compiler using in Makefile.am.
if USE_MPI
MPIDIR = $(MPICOMPILE)
MPILIB = $(MPILINK)
CXX=#MPICXX#
F77=#MPIF77#
MPILIBS=$(MPILINK)
endif
I get
CXX was already defined in condition TRUE, which includes condition USE_MPI ...
configure.ac:12: ... `CXX' previously defined here
I don't have a rule that specifies the compiler, so maybe there is a way to do that.
SUBDIRS = .
bin_PROGRAMS = check.cmr
check_ccmr_SOURCES = check_gen.cpp
check_ccmr_CXXFLAGS = -I$(INCLUDEDIR) $(MPIDIR)
check_ccmr_LDADD = -L$(LIBDIR)
check_ccmr_LDFLAGS = $(MPILIB)
If you have disabled the subdir-objects option to automake, something like this might work:
configure.ac:
AC_ARG_ENABLE([seq], ...)
AC_ARG_ENABLE([mpi], ...)
AM_CONDITIONAL([ENABLE_SEQ], [test $enable_seq = yes])
AM_CONDITIONAL([ENABLE_MPI], [test $enable_mpi = yes])
AC_CONFIG_FILES([Makefile seq/Makefile mpi/Makefile])
Makefile.am:
SUBDIRS =
if ENABLE_SEQ
SUBDIRS += seq
endif
if ENABLE_MPI
SUBDIRS += mpi
endif
sources.am:
ALL_SOURCES = src/foo.c src/bar.cc src/baz.cpp
seq/Makefile.am:
include $(top_srcdir)/sources.am
bin_PROGRAMS = seq
seq_SOURCES = $(ALL_SOURCES)
mpi/Makefile.am:
include $(top_srcdir)/sources.am
CXX = $(MPICXX)
AM_CPPFLAGS = -DWITH_MPI
bin_PROGRAMS = mpi
mpi_SOURCES = $(ALL_SOURCES)
The only thing stopping you from doing both of these in the same directory is the override of $(CXX). You could, for instance, set mpi_CPPFLAGS and automake would handle that gracefully, but the compiler switch makes it a no-go here.
A possible workaround for not using different sources could be:
myprog.seq: myprog.cxx
$(CXX) ... myprog.cxx
myprog-mpi.cxx: myprog.cxx
#cp myprog.cxx myprog-mpi.cxx
myprog.mpi: myprog-mpi.cxx
$(MPICXX) -DWITH_MPI ... myprog-mpi.cxx
#rm -f myprog-mpi.cxx
for Automake:
myprog-bin_PROGRAMS = myprog-seq myprog-mpi
myprog_seq_SOURCES = myprog.c
myprog-mpi.c: myprog.c
#cp myprog.c myprog-mpi.c
myprog_mpi_SOURCES = myprog-mpi.c
myprog_mpi_LDFLAGS = $(MPI_CXXLDFLAGS)
INCLUDES = $(MPI_CXXFLAGS)
BUILT_SOURCES = myprog-mpi.c
CLEANFILES = myprog-mpi.c
Here is the solution that I came up with for building a two static libraries - one with MPI (libmylib_mpi.a) and one without (libmylib.a). The advantage of this method is that there is no need for duplicate source files, a single Makefile.am for both variants, and capability to use subdirs. You should be able to modify this as needed to produce a binary instead of a library. I build the non-MPI library as normal, then for the MPI variant, I leave _SOURCES empty and use _LIBADD instead, specifying an extension of .mpi.o for the object files. I then specify a rule to generate the MPI object files using the MPI compiler.
Overall file / directory structure is something like
configure.ac
Makefile.am
src
mylib1.cpp
mylib2.cpp
...
include
mylib.h
...
configure.ac:
AC_INIT()
AC_PROG_RANLIB
AC_LANG(C++)
AC_PROG_CXX
# test for MPI, define MPICXX, etc. variables, and define HAVE_MPI as a condition that will evaluate to true if MPI is available and false otherwise.
AX_MPI([AM_CONDITIONAL([HAVE_MPI], [test "1" = "1"])],[AM_CONDITIONAL([HAVE_MPI], [test "1" = "2"])]) #MPI optional for xio
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
There is probably a more efficient way to do the conditional check than I have listed here (I'm welcome to suggestions).
Makefile.am:
AUTOMAKE_OPTIONS = subdir-objects
lib_LIBRARIES = libmylib.a
libmylib_a_SOURCES = src/mylib_1.cpp src/mylib_2.cpp ...
#conditionally generate libmylib_mpi.a if MPI is available
if HAVE_MPI
lib_LIBRARIES += libmylib_mpi.a
libmylib_mpi_a_SOURCES = #no sources listed here
#use LIBADD to specify objects to add - use the basic filename with a .mpi.o extension
libmylib_mpi_a_LIBADD = src/mylib_1.mpi.o src/mylib_2.mpi.o ...
endif
AM_CPPFLAGS = -I${srcdir}/include
include_HEADERS = include/mylib.h
# define a rule to compile the .mpi.o objects from the .cpp files with the same name
src/%.mpi.o: ${srcdir}/src/%.cpp ${srcdir}/include/mylib.h
$(MPICXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -DWITH_MPI=1 -c $(patsubst %.mpi.o,$(srcdir)/%.cpp,$#) -o $#
#define a rule to clean the .mpi.o files
clean-local:
-rm -f src/*.mpi.o
MPI installations do (usually) ship with compiler wrappers, but there is no requirement that you use them -- MPI does not insist on it. If you want to go your own way you can write your own makefile to ensure that the C++ compiler gets the right libraries (etc). To figure out what the right libraries (etc) are, inspect the compiler wrapper which is, on all the systems I've used, a shell script.
At first sight the compiler wrappers which ship with products such as the Intel compilers are a little daunting but stop and think about what is going on -- you are simply compiling a program which makes use of an external library or two. Writing a makefile to use the MPI libraries is no more difficult than writing a makefile to use any other library.

Resources