I have the following makefile using GNU autotools:
AUTOMAKE_OPTIONS = subdir-objects
bin_PROGRAMS = app
app_SOURCES = \
core/main.cpp
nodist_app_SOURCES = \
index.cpp \
index.ecpp.js.cpp
AM_INCLUDES = -I$(top_srcdir)/src
index.cpp: index.ecpp
$(ECPPC) index.ecpp -o index.cpp
index.ecpp.js.cpp: index.ecpp.js
$(ECPPC) -b index.ecpp.js
index.ecpp:
vulcanize -o index.ecpp core/view/index.html --inline --strip --csp
What happens (in this case only for index.html):
vulcanize creates a .ecpp and a .ecpp.js file out of a .html file
those newly created files are compiled to .cpp files by the ecppc compiler
the created .cpp files are compiled with g++
I have a lot of .html files which need to be processed, how can I accomplish that?
You can use either Suffix rules or Pattern rules. In your case, both should do the job equally well.
The only difference is that Pattern rules are GNU-Make-specific (not compatible with Unix make), though the GNU manual I linked to discourages the use of the Suffix rules, probably because its possible use cases are a lot more limited than those of Pattern rules.
Related
I have a c++ project that I built with cmake. It compiles and links fine. The goal is to use Emscripten to generate code from it that will run in the browser.
From the docs on the Emscripten site here one finds:
After running the first two commands (emconfigure and emmake), seemingly successfully, I do not have any .bc file anywhere, although it actually does produce a .js and .wasm file. The docs imply there that the .js file would only result from executing the third command ./emcc.
A little further down on the same docs page you find:
Make generates linked LLVM bitcode. It does not automatically generate
JavaScript during linking because all the files must be compiled using
the same optimizations and compiler options — and it makes sense to do
this in the final conversion from bitcode to JavaScript.
so it seems it should produce some bitcode. How to do this?
(I did use the VERBOSE command as those docs suggest and although I do not see emcc being used instead of the native compiler, em++ is being used, which seems to mostly the same as emcc.)
When the Emscripten build system is used to build a project, it will always generate a bitcode file. This is regardless of the file extension of the default output file. It can't generate a different file, since that would confuse Make, with the file not being created that it was told would be. At the Emscripten website there is a note a short way down the page that says:
The file output from make might have a different suffix: .a for a static library archive, .so for a shared library, .o or .bc for object files (these file extensions are the same as gcc would use for the different types). Irrespective of the file extension, these files contain linked LLVM bitcode that emcc can compile into JavaScript in the final step. If the suffix is something else - like no suffix at all, or something like .so.1 - then you may need to rename the file before sending it to emcc.
Whatever files the build is supposed to create, even ones that are usually shared libraries, will always contain the bitcode, and can be linked directly with the rest of your project.
Edit:
I can only assume that the reason for the .js output file is because the CMake project is set up to produce an executable. It is possible that Emscripten is smart enough to create .js in that case, but I don't know for sure.
From the manpage of emscripten:
The target file, if specified (-o <target>), defines what will be generated:
<name>.js
JavaScript
<name>.html
HTML with embedded JavaScript
<name>.bc
LLVM bitcode (default)
<name>.o
LLVM bitcode (same as .bc)
I assume you can just then create a custom command where the output file has the extension .bc to produce bitcode. Seems like you could just skip the hassle potentially by going straight to producing .js from .c(pp).
Edit:
Alternatively, if you just want it as a side-effect and not the actual product:
--save-bc PATH
When compiling to JavaScript or HTML, this option will save a copy of the bitcode to the specified
path. The bitcode will include all files being linked, including standard libraries, and after any
link-time optimizations (if any).
Depending on the project, you may be able to skip configure entirely. In the past, i've specified C functions to export that my Wasm implementation would then use to quickly build from. Some C libraries require autogen to be run at a minimum, but I have bypassed configure for multi-dependency C projects.
# create bitcode library for WebAssembly module
$ emcc \
-o wasmlib.bc \
-s EXPORTED_FUNCTIONS="[ \
'_needed_c_function1' \
'_needed_c_function2', \
]" \
-I "c_lib_src/include" \
c_lib_src/*.c
# Quickly build using the bitcode we just created
$ emcc \
-o my_wasm_module.js \
-I "c_lib_src/include" \
wasmlib.bc \
my_wasm_impl.c
Up until Emscripten 1.38.x fastcomp you could use the CMake option EMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES set to ON and static libraries would end up being .bc files:
cmake -Bbuild -DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=ON
To check, inspected in a hex-editor those .bc files start with BC.
The option was removed (and throws an error) in recent upstream Emscripten versions (like 2.0.x). I still have to figure out, how it's done there.
Is there some way to arbitrarily assign an order on when the make is performed for the QMAKE_EXTRA_COMPILER option? It seems that declaration order seems to affect it, but it doesn't work it seems...
I have a bunch of fortran code that needs to be compiled then archived into a static library (using the ar command) to be used by a DLL I'm building. Iv been streamlining this in my .pro file to make everything happen in one go but am having a little trouble.
Heres the important stuff:
win32 {
gfortran.commands = gfortran $${FORTRAN_FLAGS} ${QMAKE_FILE_NAME} -c -o ${QMAKE_FILE_OUT}
gfortran.input = FORTRAN_SOURCE
gfortran.output = ../../src/SupMods/FireNetworkDLL/${QMAKE_FILE_BASE}.o
gfortran.CONFIG = target_predeps
QMAKE_EXTRA_COMPILERS += gfortran
}
win32 {
archive.commands = ar -qsc ${QMAKE_FILE_OUT} $${FORTRAN_OBJ}
archive.input = FORTRAN_OBJ
archive.output = ../../src/SupMods/FireNetworkDLL/libORAN.a
archive.CONFIG = combine target_predeps
QMAKE_EXTRA_COMPILERS += archive
}
This only works some of the time...no idea why. Also FORTRAN_SOURCE is just a list of all the fortran files (ex: fire.f95) and $${FORTRAN_OBJ} is a list of all the fortran .o files.
So is there some way I can always have the object files generated from gfortran first and follow that by the ar command? (im guessing it has something to do with dependency_type or depends...)
Also if someone has a better approach I'm all ears, first time messing with qmake really.
**Could this have something to do with the variable FORTRAN_OBJ referencing .o files that aren't actually there before the build start?
The order of processing of qmake extra compilers is determined by chaning of input/output variables of the compilers. For example, if the first compiler gets input files from the variable A and writes output file names to the variable B and the second compilers gets its files from the variable B, then the first compiller will be processed by the qmake before the second.
It is unclear from your sources how you populate FORTRAN_OBJ variable. Judging from the symptoms you report I suspect you fill the variable by hand. I suggest not to. Let the QMAKE_EXTRA_COMPILER to do the work automatically.
The following code should work (untested):
gfortran.commands = gfortran $${FORTRAN_FLAGS} ${QMAKE_FILE_NAME} -c -o ${QMAKE_FILE_OUT}
gfortran.input = FORTRAN_SOURCE
gfortran.output = ../../src/SupMods/FireNetworkDLL/${QMAKE_FILE_BASE}.o
gfortran.CONFIG = target_predeps
# the only change required I guess
gfortran.variable_out = FORTRAN_OBJ
QMAKE_EXTRA_COMPILERS += gfortran
archive.commands = ar -qsc ${QMAKE_FILE_OUT} $${FORTRAN_OBJ}
archive.input = FORTRAN_OBJ
# I suggest to use $$OUT_PWD here
archive.output = ../../src/SupMods/FireNetworkDLL/libORAN.a
archive.CONFIG = combine target_predeps
QMAKE_EXTRA_COMPILERS += archive
Do not confuse processing order (generating rules to a Makefile by qmake) with execution order (execution of the rules when running make). In general the last have to be managed carefully by specifying dependencies between targets. But in this case all needed dependencies will be generated automatically thanks to the fact that by default qmake generates a dependency for each pair of the corresponding in and out files. So in this case libORAN.a will depend on all the files in FORTRAN_OBJ variable which in turn will depend on the corresponding source fortran files and the proper sequence of events is guaranteed.
If you can read Russian there is more info about QMAKE_EXTRA_COMPILERS in my blog.
Well... ended up just adding all the object files to the final DLL instead of using a static library! Should have done that awhile ago...
I need to write a pre-build makefile which is called separately from the main build file. This make file should make a walk in a directory where it is called. There is a list of directories in another make file called 'sources.mk' with a variable which describe the directory:
SUBDIRS := \
. \
directory1 \
directory2 \
Now, I need to run a loop through this list and in this loop I need to call an utility which will process all file with a 'h' extension. I wrote this:
include Default/sources.mk
find_files:
for prefix in $(SUBDIRS); do \
for file in *.h; do \
C:/QtSDK/Desktop/Qt/4.7.4/mingw/bin/moc.exe $$prefix/$$file; \
done \
done
Run command: make -f premake.mk
I don't describe the errors, there are a lot of them, I was trying different makefiles, but I am a newbie at it and these attempts failed. Please, review my code and/or suggest other methods.
Your problem is probably just this one simple thing: You're looking for file in *.h in the current directory, not in the subdirectory. Try this instead:
for prefix in $(SUBDIRS); do \
for file in $$prefix/*.h; do \
C:/QtSDK/Desktop/Qt/4.7.4/mingw/bin/moc.exe $$file; \
done \
done
With that said, a much better way of doing this is to use make to handle the processing of all of the files (and deciding whether or not all of them need to be reprocessed!), rather than using an explicit loop in the rule. You'd start with a list of header files, as Eldar Abusalimov's answer suggests:
moc_headers := $(wildcard $(SUBDIRS:%=%/*.h))
The inner piece of that manipulates the SUBDIRS list into a form directory1/*.h, directory2/*.h, and so on, and then the wildcard function expands all the *.h patterns.
Then, you generate the list of output files from them:
moc_mocfiles := $(patsubst %.h, %_moc.cpp, $(moc_headers))
This takes that expanded list of header files directory1/header1.h, directory1/header2.h, and so on, and substitutes the %.h pattern with %_moc.cpp. (Note that, because these names all have the directory name as part of the name, you can't easily use the more common moc_%.h name pattern, because you'd get moc_directory1/header1.cpp, not the desired directory1/moc_header1.cpp. There are ways to get around that, but it's easier to avoid the problem.) In any case, this gives you a list of output files: directory1/header1_moc.cpp, directory1/header2_moc.cpp, and so on.
Now that you have a list of output files, Make knows how to iterate over those pretty easily. You just declare that list as a prerequisite of some other target that you're making, for instance:
find_files: $(moc_mocfiles)
And, finally, you give make a generic rule for making a *_moc.cpp file from a *.h file:
%_moc.cpp: %.h
C:/QtSDK/Desktop/Qt/4.7.4/mingw/bin/moc.exe $< -o $#
There, the first line indicates "this is how you make a file that fits the %_moc.cpp pattern, if you have a file fitting the %.h pattern to make it from". In the second line, the $< becomes the input file (the %.h file), and the $# becomes the output file. Here, you're explicitly telling moc.exe with the -o option to spit out a file with the %_moc.cpp name rather than whatever it uses by default.
So, putting all this together, when you make the find_files target, make will realize that it needs to make all those %_moc.cpp files in the moc_mocfiles list, and for each one it will see that it has a possible rule that fits, it will see that the rule applies because the corresponding %.h file exists, and it will apply the rule.
This also has the advantage that, if the %_moc.cpp file already exists and is newer than the %.h file, indicating that it's already up-to-date, it won't bother regenerating it next time you run make. It will only regenerate the files corresponding to the %.h files you've edited.
(Oh, and one last thing: When cutting-and-pasting all these things from this answer, make sure you get your tabs in the right places!)
Just use native wildcard function of GNU Make:
HEADERS := $(wildcard $(SUBDIRS:%=%/*.h))
I am trying to use GNU AutoTools for my C++ project. I have written configure.ac, makefile.am etc. I have some files that are used by the program during execution e.g. template files, XML schema etc. So, I install/copy these files along the executable, for which I use something like:
abcdir = $(bindir)/../data/abc/
abc_DATA = ../data/knowledge/abc.cc
Now it copies the file correctly and My program installation structure looks somethings as follows:
<installation_dir>/bin/<executableFile>
<installation_dir>/data/abc/abc.cc
Now the problem is that in the source code I actually use these files (abc.cc etc.) and for that I need path of where these files resides to open them. One solution is to define (using AC_DEFINE) some variable e.g. _ABC_PATH_ that points to the path of installation but how to do that exactly?. OR is there any better way to do that. For example, in source code, I do something like:
...
ifstream input(<path-to-abc-folder> + "abc.cc"); // how to find <path-to-abc-folder>?
..
The AC_DEFINE solution is fine in principle, but requires shell-like variable expansion to take place. That is, _ABC_PATH_ would expand to "${bindir}/../data/abs", not /data/abc.
One way is to define the path via a -D flag, which is expanded by make:
myprogram_CPPFLAGS += -D_ABC_PATH='\"${abcdir}\"'
which works fine in principle, but you have to make include config.status in the dependencies of myprogram.
If you have a number of such substitution variables, you should roll out a paths.h file that is
generated by automake with a rule like:
paths.h : $(srcdir)/paths.h.in config.status
sed -e 's:#ABC_PATH#:${abcdir}:' $< > $#
As a side-note, you do know about ${prefix} and ${datarootdir} and friends, don't you? If not, better read them up; ${bindir}/.. is not necessarily equal to ${prefix} if the user did set ${exec_prefix}.
I have several hundred files in a non-flat directory structure. My Makefile lists each sourcefile, which, given the size of the project and the fact that there are multiple developers on the project, can create annoyances when we forget to put a new one in or take out the old ones. I'd like to generalize my Makefile so that make can simply build all .cpp and .h files without me having to specify all the filenames, given some generic rules for different types of files.
My question: given a large number of files in a directory with lots of subfolders, how do I tell make to build them all without having to specify each and every subfolder as part of the path? And how do I make it so that I can do this with only one Makefile in the root directory?
EDIT: this almost answers my question, but it requires that you specify all filenames :\
I'm sure a pure-gmake solution is possible, but using an external command to modify the makefile, or generate an external one (which you include in your makefile) is probably much simpler.
Something along the lines of:
all: myprog
find_sources:
zsh -c 'for x in **/*.cpp; echo "myprog: ${x/.cpp/.o}" >> deps.mk'
include deps.mk
and run
make find_sources && make
note: the exact zsh line probably needs some escaping to work in a make file, e.g. $$ instead of $. It can also be replaced with bash + find.
One way that would be platform independent (I mean independent from shell being in Windows or Linux) is this:
DIRS = relative/path1\
relative/path2
dd = absolute/path/to/subdirectories
all:
#$(foreach dir, $(DIRS), $(MAKE) -C $(dd)$(dir) build -f ../../Makefile ;)
build:
... build here
note that spaces and also the semicolon are important here, also it is important to specify the absolute paths, and also specify the path to the appropriate Makefile at the end (in this case I am using only one Makefile on grandparent folder)
But there is a better approach too which involves PHONY targets, it better shows the progress and errors and stops the build if one folder has problem instead of proceeding to other targets:
.PHONY: subdirs $(DIRS)
subdirs: $(DIRS)
$(DIRS):
$(MAKE) -C $# build -f ../../Makefile
all : prepare subdirs
...
build :
... build here
Again I am using only one Makefile here that is supposed to be applicable to all sub-projects. For each sub-project in the grandchild folder the target "build" is created usinf one Makefile in the root.
I would start by using a combination of the wildcard function:
http://www.gnu.org/software/make/manual/make.html#Wildcard-Function
VPATH/vpath
http://www.gnu.org/software/make/manual/make.html#Selective-Search
and the file functions
http://www.gnu.org/software/make/manual/make.html#File-Name-Functions
For exclusion (ie: backups, as Jonathan Leffler mentioned), use a seperate folder not in the vpath for backups, and use good implicit rules.
You will still need to define which folders to do to, but not each file in them.
I'm of two minds on this one. On one hand, if your Make system compiles and links everything it finds, you'll find out in a hurry if someone has left conflicting junk in the source directories. On the other hand, non-conflicting junk will proliferate and you'll have no easy way of distinguishing it from the live code...
I think it depends on a lot of things specific to your shop, such as source source control system and whether you plan to ever have another project with an overlapping code base. That said, if you really want to compile every source file below a given directory and then link them all, I'd suggest simple recursion: to make objects, compile all source files here, add the resultant objects (with full paths) to a list in the top source directory, recurse into all directories here. To link, use the list.