I am building a cmake project with several transitive dependencies. E.g., say I have executable ex1 which dependends on lib1. lib1 requires lib2. This could be visualized as such: (ex1 -> lib1 -> lib2).
Hitherto I linked them publicly to express said dependencies. So the CMakeLists.txt for lib2 would have a line:
target_link_libraries(lib1 PUBLIC lib2)
target_link_libraries(ex1 PUBLIC lib1)
Thus lib1 has all includes form ex1 and lib1 all those from lib2. Linking order is ok etc. The problem with this approach is, that cmake waits until requirements are built before it proceeds. I.e. in the above example (ex1 -> lib1 -> lib2), I wait for lib1 until lib2 is built and ex1 build is not started until lib1 is built.
lib1 in this case is a library, not an executable. Though I need some information about linking order and lib1 needs lib2's include directories, it is not necessary for lib1 to wait until lib2 is compiled and linked. ex1 needs lib1 and lib2 when linking, but as long as there are no shenanigans in the source code, it is not necessary for ex1 to wait for the lib1 build to finish to start compiling and lib1 to wait for the lib2 build to finish before compiling.
The motivation behind this is, that a few source files take much longer to compile than the rest. I have access to a compile cluster and would like to task it to capacity to reduce built times. When those single-file-compilations take a long time, the compile cluster is basically compiling a single file on a single thread while it could proceed with the other hundreds of files.
Is there a straight forward way to achieve this in cmake?
#fabian is correct. The default generator on linux is Make. Ninja, for example, handles dependencies differently and leads to a significant speedup in my case.
Related
I come from many years of experience with make. One thing that is baffling me is the use of task dependencies rather than file dependencies in Gradle. For example, if I have a C program that has these dependencies (in makefile format):
app : file1.o file2.o
file1.o : file1.c file1.h file2.h
file2.o : file2.c file2.h
So, both object files are dependent on file2.h and would be rebuilt if file2.h changed. However, if file1.h changed, only file1.o would be built.
How can I represent this in Gradle? I am mainly interested in how one can handle this in raw Gradle as opposed to using a plugin.
Thanks!
Blake McBride
The answer has to do with Gradle's incremental build support. It is documented at https://blog.gradle.org/introducing-incremental-build-support and https://docs.gradle.org/current/userguide/more_about_tasks.html#sec:up_to_date_checks
Basically, for built-in tasks, Gradle internally calculates what the input and output files associated with a task are. It then uses this information to avoid executing unneeded tasks thus eliminating unneeded steps. For custom tasks, Gradle has a method, documented in the above links, to tell Gradle what the input and output files are for a particular task.
I am currently working on a project where I have a couple applications in a parent folder that need to be rebuilt whenever the libraries contained in child folders are updated. The apps in the parent folder are built with a makefile, and the libraries are built with a separate makefile in the respective folder. This looks something like :
ParentDir
app1
app2
Makefile
libdir1
Makefile
libdir2
Makefile
I'm currently doing something like this for my makefile in the parent dir
all : app1 app2
libs = libdir1/lib1.a libdir2/lib2.a
.PHONY : $(libs)
$(all) : $(libs)
#do stuff to make the apps
libdir1/lib1.a :
$(MAKE) -c libdir1
libdir2/lib2.a :
$(MAKE) -c libdir2
My problem is, I don't want the apps in the parent dir's makefile to rebuild unless one of the makefiles it "depends" on are updated. I know that the reason this is happening currently is that I have my libs declared as PHONY ( so they always rebuild ), but that was the only way I could figure out to actually call the children makefiles.
So, what I want is for each app to build only when either of the libdirs makefile's would actually do something, and to call each libdir's makefile that would "do something" before building the app.
Thanks for your help in advance.
You should make a dummy dependency for the libraries so that their Makefiles are always processed. Here is a good example and explanation: http://owen.sj.ca.us/~rk/howto/slides/make/slides/makerecurs.html
It's been a while that I've been looking for this, I need a tool to automatically create a makefile for my project
I've seen qmake and cmake, the problem is that I have two targets (Client and server) they both use a common library (which I wrote) and I want it to create two targets for me, cmake and qmake don't do this
ty
set(servers_srcs
server.cpp
foo.cpp
bar.cpp
)
set(client_srcs
client.cpp
xyz.cpp
abc.cpp
)
set(library_srcs
lib.cpp
)
add_library(library ${library_srcs})
add_executable(client ${client_srcs})
target_link_libraries(client library)
target_link_libraries(server library)
This automatically creates your Makefile, with three targets: client server and library.
I'm having trouble with a directory dependency in a parallel build in SCons.
Consider two projects with a single SConstruct in the following (simplified) hierarchy:
- SConstruct
- project1
- src
- project2
- src
- build
- project1
- project2
- dist
- project1
- project2
Each of project1 and project2 are supposed to be built under the relevant build directory (using variant dir) and several targets needs to be installed under the relevant dist directory.
Project 2 depends on Project 1's dist. I've states this dependency explicitly using the Depends() statement like so:
Depends('project2', 'dist/project1')
When I use a non-parallel build, there's no problem. Project 1 is fully built, targets are installed in the dist directory, and only then project 2 is built. However, when I use multiple jobs (4), project 2 is being built simultaneously to the Install() builder being run for the files needed to be installed in project 1's dist directory.
So, my questions are:
Does the Depends(project2, dist/project1) statement refers to the creation of the dist/project1 directory or to the completion of building all the directory's children?
How should I solve this issue?
Thank you very much,
BugoK.
Instead of specifying the actual directories as strings in the Depends() function, try specifying the actual targets as returned by the SCons project1 and project2 builders. Every SCons builder (or at least most of them) returns the affected target as an object, and its better to use this object instead of the file/directoy name since if you dont use the exact same file/directory path, it wont be considered as the same target.
Here is an example, fill in content accordingly:
project2Target = Install()
# Im not sure how you're building project1, so replace the builder
project1Target = Proj1DistBuiler()
Depends(project2Target, project1Target)
Let's say I have a main target, exe which depends on three libs:
exe: LIB1.lib LIB2.lib LIB3.lib
and the lib targets have something like this:
LIB1: $(LIB1OBJECTS)
LIB2: $(LIB2OBJECTS)
LIB3: $(LIB3OBJECTS)
Giving that most of the time, make will be run with a -j flag, and I would like for LIB1 and LIB2 to be built in parallel, how can I make sure that LIB3 is always built after LIB2?
Make LIB3 dependent on LIB2.