How to read file from Makefile? - makefile

I am using GNU Make to build a multiple-directory project.
My question is how can I use single makefile to build multiple devices?
e.g. My application has to run on various X,Y,Z mobile devices each having different properties like screensize, keyboard type, platform version etc. I have to pass make -f <makefilename> <targetname>. Here targetname can be device name and model like Samsung CorbyPlus, but my makefile has to go to particular dirname of samsung and open the .txt file or so where all above properties are defined. I have to read all of them during build time and access in my code through some macros/defines/flags.
Can anyone suggest how to do this? Even better solution for my requirement will be appreciated.

I'd suggest using configuration makefiles. For example, suppose you have several device with its configurations:
config_device1.mk
OPTION1=yes
OPTION2=0
config_device2.mk
OPTION1=no
OPTION2=1
Then you can conditionally include them into base makefile using special parameter passed from command line (make -f makefile DEVICE=dev_type1) and use options from configuration files and process them:
makefile
ifeq ($(DEVICE),dev_type1)
include $(CONFIG_PATH)/config_device1.mk
endif
ifeq ($(DEVICE),dev_type2)
include $(CONFIG_PATH)/config_device1.mk
endif
ifeq ($(OPTION1),yes)
CFLAGS += -DBUILD_OPTION1
endif
CFLAGS += -DBUILD_OPTION2=$(OPTION2)
BTW, for a long perspective (if you don't have time constraints now) it's better to use some of existing build system, read its manual and stick to its methodology.

Related

make is not using -std=c++11 option for g++

I am trying to compile c++ files using make. But, it is not using -std=c++11 flag by default. Whenever I need to compile a program which uses c++11 specific features, I have to explicitly compile it using g++.
So, I want to ask how can I have make automatically use the option -std=c++11 for all my c++ files on my system.
If I need to change some global makefile for g++ , what is the location of the makefile on Linux Mint 18 and what needs to be changed or added?
Or do I need to create a Makefile for myself?
EDIT 1: I am invoking make like make myfile
And there are only .cpp files and their binaries in the directory. I don't have any Makefile in the directory.
EDIT 2: Here, myfile is the name of the c++ file which I want to compile.
When I run make with the -d option, I get the following output (I can not paste all of the output as it is quite long and is exceeding the body size limit so, I am including the screenshots of the output).
Image 1
And this image(2) has some lines from the end.
Image 2
I intentionally made a change in the file "MagicalWord.cpp" so that make finds something to make!
There is no "global makefile" and there is no way to change the default flags for all invocations of make (unless you edit the source code to GNU make and compile it yourself, which is a bad idea in this situation).
In your makefile(s), add the line:
CXXFLAGS += -std=c++11
Assuming you're using the built-in rules for compiling things, or that you're using the standard variables with your own rules, that will do what you need.
If that doesn't work we'll need to see your makefile or at least the rules you use to build your C++ source files (things like the -d output aren't useful here--that would be interesting if files weren't being built, that you thought should be or similar).
Setting a system-wide language for all your C++ projects isn't necessarily a good idea. Instead, define a Makefile that specifies any compiler options you'd like:
CXXFLAGS := -std=c++11 $(CXXFLAGS)
The CXXFLAGS are then passed to your compiler when compiling a C++ program (assuming you're using the default GNU Make rules).
If the Makefile lives in your current working directory, you can now run make target in order to compile a target.cpp file into a target executable.
If the Makefile is in another directory, you must specify the path to it:
make -f path/to/your/Makefile target
If you want to add extra parameters just for one run, you can set an environment variable or a make variable on the command line:
# environment:
CXXFLAGS='-std=c++11' make target
# make variable:
make target CXXFLAGS='-std=c++11'
Any of these will cause the execution of g++ -std=c++11 target.cpp -o target or equivalent.
In theory you can edit your shell profile to export CXXFLAGS='-std=c++11' which will make that environment variable available to all programs you run. In practice, setting compiler options through environment variables tends to cause more problems than it solves.
Of all these solutions, just writing a normal Makefile is by far the easiest approach. That way, all of the build configuration is in one place and completely automated.

Makefile - Deduce targets from sources (on iSeries system)

On an IBM i system, using PASE (AIX emulator), i try to compile RPG sources using a makefile.
I have RPG sources and try to build a PGM program.
Every single source will be compile in a distinct PGM.
Here is the syntax i tried first
VPATH=.
SYSTEM=system -iv
CRTRPGMOD=CRTRPGMOD
BIN_LIB=MR_CH
CURRENT_PATH=/currentPath #${PWD} doesn't work
#With this line active, it works
SRC_RPGLE = src1.rpgle src2.rpgle
#With this line active, it doesn't work
#SRC_RPGLE = $(shell echo *.rpgle) #Should list every sources i want to compile
TARGETS = $(SRC_RPGLE:.rpgle=.rpgleMod) #Should list every program i want to build
.SUFFIXES: .rpgle .rpgleMod
.rpgle.rpgleMod:
$(SYSTEM) "$(CRTRPGMOD) MODULE($(BIN_LIB)/$(*F)) SRCSTMF('$(CURRENT_PATH)/$<')" > $(*F)_1_crtrpgmod.log
ln -fs $(*F).rpgMod
all: $(TARGETS)
I tried to apply GNU shell syntax using AIX make command
Any suggestions ?
I'm not familiar with the AIX implementation of make but assuming that the linked man page is all there is to it, then it looks like a bare-bones implementation of POSIX make (for an older POSIX spec).
Therefore, the only way to do what you want (expand a list of files) is to use recursion, so that you get access to the shell, like this:
SYSTEM=system -iv
CRTRPGMOD=CRTRPGMOD
BIN_LIB=MR_CH
CURRENT_PATH=/currentPath
CURRENT_PATH=/home/CHARLES/Projets/MRSRC/tmp
recurse:
$(MAKE) all SRC_RPGLE="`echo *.rpgle`"
TARGETS = $(SRC_RPGLE:.rpgle=.rpgleMod)
.SUFFIXES: .rpgle .rpgleMod
.rpgle.rpgleMod:
$(SYSTEM) "$(CRTRPGMOD) MODULE($(BIN_LIB)/$(*F)) SRCSTMF('$(CURRENT_PATH)/$<')" > $(*F)_1_crtrpgmod.log
ln -fs $(*F).rpgMod
all: $(TARGETS)
The recurse rule MUST be the first target in the makefile. Also this won't help if you want to run other targets like make foobar; it will only help you run all properly.
Alternatively you can obtain GNU make and build it for your system, and use that. In the end that might be a more straightforward approach.

Makefile to compile Fortran source files in different directories

Here is my problem: I have been using Java for many years and enjoy having many directories separating different areas of the code. For my current project I am writing Fortran code, which should compile under Windows and Unix/Linux. For Windows, I am using Eclipse/Photran with MinGW/gfortran tools to set up Makefiles.
Here is the desired project structure (deep nesting tree-like Java-like would be even nicer)
dir1/src/*.f95
dir1/make/Makefile_lib1.any
dir1/make/Makefile_lib1.win
dir1/make/Makefile_lib1.unix
dir2/src/*.f
dir2/make/Makefile_lib2.any
dir2/make/Makefile_lib2.win
dir2/make/Makefile_lib2.unix
...
dir_main/src/*.f or *.f95
dir_main/make/Makefile_main.any
dir_main/make/Makefile_main.win
dir_main/make/Makefile_main.unix
I would like to call make Makefile_main.unix, which would set up any Unix-specific variables and then include Makefile_main.any, Makefile_lib1.any, ...
(similar for making on Windows)
I got to the stage where I can see all source files in a given directory, e.g.
SRCS := $(wildcard $(SRC_DIR)/*.$(SRC_EXT))
Now I am struggling with how to make all dependencies as in Fortran 95 each source generates *.o and *.mod.
Is there a way to switch between directories when compiling so that all targets/dependencies do not have dir-path in their names? Note that I am calling make from some other service directory where the Eclipse project lives. Any suggestions how to proceed?
I really do not want to do the usual Fortran style of having just one directory with
all the mess together with the code.
There are two major strategies you can take.
You can place a makefile in each subdirectory and have it support targets like all, clean etc, then use recursive make invocations from the top-level makefile to make the same target (e.g. all) in every subdirectory.
Alternatively, you can handle it all in one make invocation, without recursing, but then you'll have to work with relative paths containing subdirectory names. Personally I don't see a problem with it, and I've maintained a system of makefiles based on this approach.
Here is what you can do in your case, assuming that SRC is set correctly to the list of relative paths to every source you need to compile.
# This replaces the SRC_EXT suffix with .o in each filename
OBJ = $(SRC:%.$(SRC_EXT)=%.o)
$(BINARY_NAME): $(OBJ)
...link command...
%.o: %.$(SRC_EXT)
...compile command...

How to control output generated from extconf.rb depending on OS?

I'm writing a Ruby C Extension. I will be compiling it under Windows and OSX.
What I have been unable to work out is control where the makefile and all the rest of the generated files are placed.
My extconf.rb file got conditional statements for preparing the makefile depending on the OS - so I use one for both of them.
I would like that when I compile under OSX it is all placed in an osx folder and similary under a win folder under Windows in order to keep it all separated.
As it is now all the files are generated in the same folder as my source code.
(I am very green to C and compiling applications. sorry if I have missed something obvious.)
I could write a batch to move the files afterwards, but I find it cleaner if it could be done during generation.
You could put a conditional in the makefile, before the rules. Something like:
OS := $(shell uname)
ifeq ($(OS),Darwin)
FOLDER := /some_path/osx_folder
else
FOLDER := /some_other_path/win_folder
endif
EDIT:
FOLDER is just a variable; it is to be used later in the makefile, like so:
$(FOLDER)/main: $(FOLDER)/main.o $(FOLDER)/foo.o
blah blah link $^ together to build $#
$(FOLDER)/%.o: $(SOURCE_DIRECTORY)/%.c
blah blah compile $< to build $#
(This is a crude example-- more elegant solutions are possible if you have a lot of files to deal with.)
I looked at the source of mkfm.rb and found that if you changed the current directory the Makefile was the current one.
Dir.chdir( OUTPUT_PATH )
create_makefile( EXTENSION_NAME, SOURCE_PATH )
That created the makefile in OUTPUT_PATH. As you see, I then had to provide SOURCE_PATH to create_makefile to account for the face the Makefile wasn't in the same location as the source files.

moving from make to cmake: how to use build target with wildcards

I'm trying to convert an makefile-build to cmake (to avoid the current state of being forced to take care for the windows-build env based on make/msdev and the linux based on make/gcc).
In this project, I've found a directory full of sourcecode files that get, based on a naming convention, compiled to libraries. (e.g. c1223.c => c1223.dll (or .sl) )
The current makefile consists of some directives using wildcards, e.g.:
LIB_NO = $(basename $(subst s,,$#))
OBJ = $(OBJ_PATH)/s$(LIB_NO).o $(OBJ_PATH)/c$(LIB_NO).o\
$(OBJ_PATH)/b$(LIB_NO).o
$(OBJ_PATH)/%.o : %.c
-$(CC) $(CFLAGS) -I$(PWD) -c $< -o $#
-(chmod a+w $#;true)
I've searched for a while but can't find anything that seems to work. Is it even possible with cmake to let it generate a wildcard based build?
Any comments, hints and suggestions are very welcome :)
cheers
Markus
You can use fairly primitive globbing (there's no regular expression syntax that I can see).
file(GLOB TESTSRCS "test/src/*.cpp")
# Compile the test sources.
add_executable(Tests ${TESTSRCS})
target_link_libraries(Tests ${LIB} gtest gtest_main)
The actual makefiles do not seem to contain wildcard searches inside them. If you add new files you will need to re-run cmake.
What I don't know is how you would manage to wrap up the library creation in a single macro if you have many different library files to generate.
You might be able to do something like this if there's only one c file per library:
file(GLOB libfiles "path/to/libs/c*.c")
foreach(libfile ${libfiles})
GET_FILENAME_COMPONENT(libname ${libfile} NAME) # remove the '.c' part (untested, hopefully this will work)
add_library(${libname} ${libfile})
endforeach(libfile)
If anybody else has a better solution, I would also like to learn it.
CMake does not generate makefiles that have wildcard-based rules in them. It generates specific rules for the files that it knows about.
In your example, you are explicitly listing the .o files that comprise your library. In CMake, you would instead explicitly list the source files that contribute to your library, and then let CMake take care of the rest.
Do you need makefiles that have wildcard-based rules in them for some reason?
Couldn't you simply construct a list of the source files, and then, for each element in the list, do an "add_library" call with the source file and a library name constructed from the source file name?

Resources