View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0014312CMakeCMakepublic2013-07-25 09:142016-06-10 14:31
ReporterWojciech Knapik 
Assigned ToKitware Robot 
PriorityhighSeveritymajorReproducibilityalways
StatusclosedResolutionmoved 
Platformx86_64OSLinuxOS Version
Product VersionCMake 2.8.10.2 
Target VersionFixed in Version 
Summary0014312: Parallel builds using make break when two or more targets that share a dependency (or are dependent) are called explicitly
DescriptionIn the example below, the top level targets for "main" and "empty" have recipes that call make. When make is called with -j, the two instances of make are called in parallel and, knowing nothing about each other, race to finish the same task.

In the real world, this breaks builds in very common use cases. E.g. when you have 3 types of tests - ut, mt and it - it is reasonable to call `make -j24 ut mt it'. If those targets happen to share dependencies, the build will break.

Creating top level targets that cover all such combinations is not an acceptable solution.
Steps To Reproduce$ cat CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(foo)
add_library(empty STATIC empty.cpp)
add_custom_command(TARGET empty POST_BUILD COMMAND echo whoops)
add_executable(main main.cpp)
target_link_libraries(main empty)
$ cd build
$ cmake ..
$ make -j empty main|grep whoops
whoops
whoops
$
TagsNo tags attached.
Attached Files

 Relationships
has duplicate 0015286closed ExternalProject double build with parallel make and multiple targets 

  Notes
(0033608)
Brad King (manager)
2013-07-25 09:17
edited on: 2013-07-25 09:18

This is a known problem that has existed forever. The generated makefiles simply do not support multiple explicit targets on the command line. It is a problem with how the per-directory command-line entry-point/front-end Makefile layout works. No one has been bothered by it enough to propose a solution.

(0033615)
Wojciech Knapik (reporter)
2013-07-25 16:07

I'm bothered enough and I propose never calling make from a recipe instead of using the dependency mechanism.

I get the feeling that the unholy combination of "it's always been like that" and "no one has bothered" will leave this bug with a "wontfix" resolution and that would not be right. Anyone reading make documentation will learn, that it's perfectly correct to call multiple targets at once, but if they do, with a CMake-generated build system, their build will break for no apparent reason. That is simply wrong.

At least add this to the makefiles, so people won't waste time debugging it:

ifeq ($(filter 0 1,$(words $(MAKECMDGOALS))),)
$(error Duuude, two targets at a time ? Such advanced technology does not exist yet)
endif

At least it'll be funny for a moment ;]
(0033617)
Brad King (manager)
2013-07-25 16:20

The multi-level make invocation is explained in this FAQ entry:

 http://www.cmake.org/Wiki/CMake_FAQ#Why_does_CMake_generate_recursive_Makefiles.3F [^]

It's the first level's invocation of the second level that needs to be re-worked and perhaps combined. However, the first level is what allows one to run "make" from any subdirectory to build the targets their along with dependencies so there must be a separate Makefile in each directory. Supporting both at the same time is not a trivial change from the current design.

Any solution must work with ancient UNIX make and cannot depend on GNU make features.

See also the Ninja generator and ninja build tool as mentioned in the FAQ entry.
(0033620)
David Cole (manager)
2013-07-26 18:07

You say:

"it is reasonable to call `make -j24 ut mt it'"

It is also reasonable to call "make -j24 ut && make -j24 mt && make -j24 it" and serialize a little bit to get a mostly parallel invocation to work with existing CMake...

Just mentioning it as a possibility for those who might want to take the easy way, but still get most of the gain of a -j24 with multiple targets.

I agree that it would be nice to have something done about this..... but most of my time is spent in Visual Studio anyhow. I certainly wouldn't want to tackle a re-design of the Unix Makefiles parts of CMake personally. ;-)
(0034773)
Robert·Luberda (reporter)
2013-12-14 05:13

I've recently encountered the same issue, and spent some time on investigating it. It seems to me that even if proper fix would require re-desing of entire generator, the work-around is quite simple: just disallow the parallel executions of tasks by adding the .NOTPARALLEL: target into the top-level Makefile.

Thanks to it the `make -j24 ut mt it' command will work as `"make -j24 ut && make -j24 mt && make -j24 it' at least with GNU make; honestly I have no idea if it is a GNU make only feature or not, but my gut feeling is that other make commands will either support it, or ignore it (by treating .NOTPARALLEL as a `doing nothing' target)
(0034818)
Brad King (manager)
2013-12-19 09:55
edited on: 2013-12-20 09:38

Re 0014312:0034773: Wonderful! It is easy to add .NOTPARALLEL to the directory-level Makefile command-line entry points:

 Makefile: Allow "gmake target1 target2 -j"
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bd11de08 [^]

It won't solve the problem on make implementations that do not support .NOTPARALLEL but it won't hurt them either. On the popular GNU make it will work as desired. Thanks.

(0035501)
Ben Boeckel (developer)
2014-03-24 18:32

Should this be closed?
(0035531)
Brad King (manager)
2014-03-26 11:10

Re 0014312:0035501: Currently the solution only works with GNU make tools. I left the issue open in the backlog in case anyone ever wants to work on a more general solution.
(0037863)
raspy (reporter)
2015-01-30 05:37
edited on: 2015-01-30 06:18

This workaround generates Makefiles which are no longer parsable by Clearmake:

$ clearmake
clearmake: Error: Syntax error in file "Makefile", line 10, column 21
syntax error
$ head -n 10 Makefile | tail -n 1
.PHONY : .NOTPARALLEL

I believe the only offending line is the '.PHONY: .NOTPARALLEL' line, not the .NOTPARALLEL itself. I think that at least this one line should be removed and just leave '.NOTPARALLEL:' in Makefile in order to be usable with Clearmake.

As an additional side effect, when I removed this offending line, Clearmake is able to parse the Makefile and starts building, but it seems that .NOTPARALLEL is in effect also for Makefile2 and in effect one is no longer able to use any parallel compilation with Clearmake whatsoever.

Edit: After further investigation it turned out that Clearmake has some strange logic about running in parallel and it does not pass -J flag information to sub-makes. It is possible however to work around this behavior by setting CCASE_CONC environment variable (and it worked the same with CMake 2.8.12.2). Therefore I believe that the only change required to make CMake's 3.0 Makefiles readable by Clearmake is to drop this '.PHONY: .NOTPARALLEL' definition.

(0037865)
Brad King (manager)
2015-01-30 08:42

Re 0014312:0037863: The .PHONY rule is not specific to .NOTPARALLEL and will be generated for any custom command output file marked with the SYMBOLIC property:

 http://www.cmake.org/cmake/help/v3.1/prop_sf/SYMBOLIC.html [^]

The intention is to tell the make tool that the file will not actually be created and it is not an error for the file to not exist after running its rule. How should that be expressed to clearmake?
(0037866)
raspy (reporter)
2015-01-30 09:13

Yes, I know how the .PHONY target is used and Clearmake does support .PHONY targets. It just seems that its handling of .NOTPARALLEL is broken; apparently it is treated somehow special so it fails on such statement.

Maybe this could be somehow implemented to just generate .NOTPARALLEL, without .PHONY? I believe that if an ancient make does not recognize .NOTPARALLEL as a special target, it will not be really affected even if .NOTPARALLEL file exists.
(0037867)
Brad King (manager)
2015-01-30 09:59

Re 0014312:0037866: Okay. It is easy to generate .NOTPARALLEL specifically without .PHONY:

 Makefile: Generate .NOTPARALLEL without .PHONY
 http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3cec0c75 [^]
(0038285)
raspy (reporter)
2015-03-24 12:01

I have just checked CMake 3.2.1 with Clearmake and syntax error is no longer reported. The fix seems to be working. Thank you.
(0042327)
Kitware Robot (administrator)
2016-06-10 14:29

Resolving issue as `moved`.

This issue tracker is no longer used. Further discussion of this issue may take place in the current CMake Issues page linked in the banner at the top of this page.

 Issue History
Date Modified Username Field Change
2013-07-25 09:14 Wojciech Knapik New Issue
2013-07-25 09:17 Brad King Note Added: 0033608
2013-07-25 09:17 Brad King Status new => backlog
2013-07-25 09:18 Brad King Note Edited: 0033608
2013-07-25 16:07 Wojciech Knapik Note Added: 0033615
2013-07-25 16:20 Brad King Note Added: 0033617
2013-07-26 18:07 David Cole Note Added: 0033620
2013-12-14 05:13 Robert·Luberda Note Added: 0034773
2013-12-19 09:55 Brad King Note Added: 0034818
2013-12-20 09:38 Brad King Note Edited: 0034818
2014-03-24 18:32 Ben Boeckel Note Added: 0035501
2014-03-26 11:10 Brad King Note Added: 0035531
2014-12-05 09:14 Brad King Relationship added has duplicate 0015286
2015-01-30 05:37 raspy Note Added: 0037863
2015-01-30 06:18 raspy Note Edited: 0037863
2015-01-30 08:42 Brad King Note Added: 0037865
2015-01-30 09:13 raspy Note Added: 0037866
2015-01-30 09:59 Brad King Note Added: 0037867
2015-03-24 12:01 raspy Note Added: 0038285
2016-06-10 14:29 Kitware Robot Note Added: 0042327
2016-06-10 14:29 Kitware Robot Status backlog => resolved
2016-06-10 14:29 Kitware Robot Resolution open => moved
2016-06-10 14:29 Kitware Robot Assigned To => Kitware Robot
2016-06-10 14:31 Kitware Robot Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team