compile concurrently, link seriallyWhy does the order in which libraries are linked sometimes cause errors in GCC?Embedding DLLs in a compiled executableHow to speed up c++ linking timeWhy does C++ linking use virtually no CPU?How does the compilation/linking process work?Linking errors when trying to compile FubiDoes C++ Builder linker support function-level linking?Difference between using Makefile and CMake to compile the codeCompiling an application for use in highly radioactive environments(Eclipse oxygen/Linux) linker C/C++ RAM usage

MAXDOP Settings for SQL Server 2014

Should I install hardwood flooring or cabinets first?

Drawing ramified coverings with tikz

A social experiment. What is the worst that can happen?

How do I repair my stair bannister?

How do ground effect vehicles perform turns?

Should I stop contributing to retirement accounts?

Global amount of publications over time

Why has "pence" been used in this sentence, not "pences"?

Could solar power be utilized and substitute coal in the 19th Century

What major Native American tribes were around Santa Fe during the late 1850s?

What is the gram­mat­i­cal term for “‑ed” words like these?

List of people who lose a child in תנ"ך

Is there a conventional notation or name for the slip angle?

On a tidally locked planet, would time be quantized?

Is a model fitted to data or is data fitted to a model?

Query about absorption line spectra

Is it possible to have a strip of cold climate in the middle of a planet?

Did arcade monitors have same pixel aspect ratio as TV sets?

Folder comparison

Indicating multiple different modes of speech (fantasy language or telepathy)

About a little hole in Z'ha'dum

What (else) happened July 1st 1858 in London?

Why did the EU agree to delay the Brexit deadline?



compile concurrently, link serially


Why does the order in which libraries are linked sometimes cause errors in GCC?Embedding DLLs in a compiled executableHow to speed up c++ linking timeWhy does C++ linking use virtually no CPU?How does the compilation/linking process work?Linking errors when trying to compile FubiDoes C++ Builder linker support function-level linking?Difference between using Makefile and CMake to compile the codeCompiling an application for use in highly radioactive environments(Eclipse oxygen/Linux) linker C/C++ RAM usage













2















I have big cmake/c++/linux project: a lot of small static libraries, a few big and interdependent static libraries, a few big executable binaries. Single binary with debug symbols is several GB. There are ~10 such binaries (worker, testA, testB, testC...). Compilation usually takes more time than we would like, but we have fast build server and we use make -j20. The worst though is linking. Single linking takes about 60 seconds and 4GB RAM. But when all final binaries are linked at the same time (happens often when 1 small sublibrary was modified, little to recompile, a lot to relink), 10 linkers use 40GB RAM (for 1 developer, there may be more) and very long time. IO is most likely the bottleneck.



We have many developers on 1 strong server and everybody uses make -j20 -l30 so that we don't overload CPU. But we don't have method for limiting number of concurrent linkers. It would be great to limit number of working linkers globally on server, but per make invocation would help as well. Ideally make -j20 -l30 --concurrent-linkers=2. Is it possible?



We use gold linker. We are in progress of separating smaller, independent modules, but this will take a long time.










share|improve this question



















  • 2





    The problem is that make itself doesn't really know what's happening, all it does is execute commands without knowing what the commands are really doing.

    – Some programmer dude
    Mar 7 at 9:05







  • 2





    As a possible workaround you could use two targets: One for compilation and one for linking. The compilation target is run using high parallelization and the linking target without.

    – Some programmer dude
    Mar 7 at 9:05











  • I might be missing the point. Using less linkers isn't going to make linking faster, is it? You'll get the first output quicker, but the last link will start much later and finish at the same time as before (assuming you do have enough RAM, of course).

    – MSalters
    Mar 7 at 10:01











  • @MSalters We have basically thin clients to central server. When linkers start abusing server, nobody can work due to overloaded IO. Secondly, we have 2nd server with less RAM - it can compile -j30 no problem, but linking -j4 causes OOM killer

    – MateuszL
    Mar 7 at 13:39






  • 1





    Are you restricted to make? CMake can also target Ninja, and Ninja supports JOB_POOL_LINK

    – MSalters
    Mar 7 at 13:44















2















I have big cmake/c++/linux project: a lot of small static libraries, a few big and interdependent static libraries, a few big executable binaries. Single binary with debug symbols is several GB. There are ~10 such binaries (worker, testA, testB, testC...). Compilation usually takes more time than we would like, but we have fast build server and we use make -j20. The worst though is linking. Single linking takes about 60 seconds and 4GB RAM. But when all final binaries are linked at the same time (happens often when 1 small sublibrary was modified, little to recompile, a lot to relink), 10 linkers use 40GB RAM (for 1 developer, there may be more) and very long time. IO is most likely the bottleneck.



We have many developers on 1 strong server and everybody uses make -j20 -l30 so that we don't overload CPU. But we don't have method for limiting number of concurrent linkers. It would be great to limit number of working linkers globally on server, but per make invocation would help as well. Ideally make -j20 -l30 --concurrent-linkers=2. Is it possible?



We use gold linker. We are in progress of separating smaller, independent modules, but this will take a long time.










share|improve this question



















  • 2





    The problem is that make itself doesn't really know what's happening, all it does is execute commands without knowing what the commands are really doing.

    – Some programmer dude
    Mar 7 at 9:05







  • 2





    As a possible workaround you could use two targets: One for compilation and one for linking. The compilation target is run using high parallelization and the linking target without.

    – Some programmer dude
    Mar 7 at 9:05











  • I might be missing the point. Using less linkers isn't going to make linking faster, is it? You'll get the first output quicker, but the last link will start much later and finish at the same time as before (assuming you do have enough RAM, of course).

    – MSalters
    Mar 7 at 10:01











  • @MSalters We have basically thin clients to central server. When linkers start abusing server, nobody can work due to overloaded IO. Secondly, we have 2nd server with less RAM - it can compile -j30 no problem, but linking -j4 causes OOM killer

    – MateuszL
    Mar 7 at 13:39






  • 1





    Are you restricted to make? CMake can also target Ninja, and Ninja supports JOB_POOL_LINK

    – MSalters
    Mar 7 at 13:44













2












2








2








I have big cmake/c++/linux project: a lot of small static libraries, a few big and interdependent static libraries, a few big executable binaries. Single binary with debug symbols is several GB. There are ~10 such binaries (worker, testA, testB, testC...). Compilation usually takes more time than we would like, but we have fast build server and we use make -j20. The worst though is linking. Single linking takes about 60 seconds and 4GB RAM. But when all final binaries are linked at the same time (happens often when 1 small sublibrary was modified, little to recompile, a lot to relink), 10 linkers use 40GB RAM (for 1 developer, there may be more) and very long time. IO is most likely the bottleneck.



We have many developers on 1 strong server and everybody uses make -j20 -l30 so that we don't overload CPU. But we don't have method for limiting number of concurrent linkers. It would be great to limit number of working linkers globally on server, but per make invocation would help as well. Ideally make -j20 -l30 --concurrent-linkers=2. Is it possible?



We use gold linker. We are in progress of separating smaller, independent modules, but this will take a long time.










share|improve this question
















I have big cmake/c++/linux project: a lot of small static libraries, a few big and interdependent static libraries, a few big executable binaries. Single binary with debug symbols is several GB. There are ~10 such binaries (worker, testA, testB, testC...). Compilation usually takes more time than we would like, but we have fast build server and we use make -j20. The worst though is linking. Single linking takes about 60 seconds and 4GB RAM. But when all final binaries are linked at the same time (happens often when 1 small sublibrary was modified, little to recompile, a lot to relink), 10 linkers use 40GB RAM (for 1 developer, there may be more) and very long time. IO is most likely the bottleneck.



We have many developers on 1 strong server and everybody uses make -j20 -l30 so that we don't overload CPU. But we don't have method for limiting number of concurrent linkers. It would be great to limit number of working linkers globally on server, but per make invocation would help as well. Ideally make -j20 -l30 --concurrent-linkers=2. Is it possible?



We use gold linker. We are in progress of separating smaller, independent modules, but this will take a long time.







c++ makefile cmake linker






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 7 at 9:21









Tsyvarev

27.6k43264




27.6k43264










asked Mar 7 at 8:58









MateuszLMateuszL

820819




820819







  • 2





    The problem is that make itself doesn't really know what's happening, all it does is execute commands without knowing what the commands are really doing.

    – Some programmer dude
    Mar 7 at 9:05







  • 2





    As a possible workaround you could use two targets: One for compilation and one for linking. The compilation target is run using high parallelization and the linking target without.

    – Some programmer dude
    Mar 7 at 9:05











  • I might be missing the point. Using less linkers isn't going to make linking faster, is it? You'll get the first output quicker, but the last link will start much later and finish at the same time as before (assuming you do have enough RAM, of course).

    – MSalters
    Mar 7 at 10:01











  • @MSalters We have basically thin clients to central server. When linkers start abusing server, nobody can work due to overloaded IO. Secondly, we have 2nd server with less RAM - it can compile -j30 no problem, but linking -j4 causes OOM killer

    – MateuszL
    Mar 7 at 13:39






  • 1





    Are you restricted to make? CMake can also target Ninja, and Ninja supports JOB_POOL_LINK

    – MSalters
    Mar 7 at 13:44












  • 2





    The problem is that make itself doesn't really know what's happening, all it does is execute commands without knowing what the commands are really doing.

    – Some programmer dude
    Mar 7 at 9:05







  • 2





    As a possible workaround you could use two targets: One for compilation and one for linking. The compilation target is run using high parallelization and the linking target without.

    – Some programmer dude
    Mar 7 at 9:05











  • I might be missing the point. Using less linkers isn't going to make linking faster, is it? You'll get the first output quicker, but the last link will start much later and finish at the same time as before (assuming you do have enough RAM, of course).

    – MSalters
    Mar 7 at 10:01











  • @MSalters We have basically thin clients to central server. When linkers start abusing server, nobody can work due to overloaded IO. Secondly, we have 2nd server with less RAM - it can compile -j30 no problem, but linking -j4 causes OOM killer

    – MateuszL
    Mar 7 at 13:39






  • 1





    Are you restricted to make? CMake can also target Ninja, and Ninja supports JOB_POOL_LINK

    – MSalters
    Mar 7 at 13:44







2




2





The problem is that make itself doesn't really know what's happening, all it does is execute commands without knowing what the commands are really doing.

– Some programmer dude
Mar 7 at 9:05






The problem is that make itself doesn't really know what's happening, all it does is execute commands without knowing what the commands are really doing.

– Some programmer dude
Mar 7 at 9:05





2




2





As a possible workaround you could use two targets: One for compilation and one for linking. The compilation target is run using high parallelization and the linking target without.

– Some programmer dude
Mar 7 at 9:05





As a possible workaround you could use two targets: One for compilation and one for linking. The compilation target is run using high parallelization and the linking target without.

– Some programmer dude
Mar 7 at 9:05













I might be missing the point. Using less linkers isn't going to make linking faster, is it? You'll get the first output quicker, but the last link will start much later and finish at the same time as before (assuming you do have enough RAM, of course).

– MSalters
Mar 7 at 10:01





I might be missing the point. Using less linkers isn't going to make linking faster, is it? You'll get the first output quicker, but the last link will start much later and finish at the same time as before (assuming you do have enough RAM, of course).

– MSalters
Mar 7 at 10:01













@MSalters We have basically thin clients to central server. When linkers start abusing server, nobody can work due to overloaded IO. Secondly, we have 2nd server with less RAM - it can compile -j30 no problem, but linking -j4 causes OOM killer

– MateuszL
Mar 7 at 13:39





@MSalters We have basically thin clients to central server. When linkers start abusing server, nobody can work due to overloaded IO. Secondly, we have 2nd server with less RAM - it can compile -j30 no problem, but linking -j4 causes OOM killer

– MateuszL
Mar 7 at 13:39




1




1





Are you restricted to make? CMake can also target Ninja, and Ninja supports JOB_POOL_LINK

– MSalters
Mar 7 at 13:44





Are you restricted to make? CMake can also target Ninja, and Ninja supports JOB_POOL_LINK

– MSalters
Mar 7 at 13:44












1 Answer
1






active

oldest

votes


















0














You could try something like:



$ cat Makefile
OBJS := foo bar baz...
EXES := qux quux quuz...

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS): ...
<compile>

$(EXES): ...
<link>


And call it with:



$ make -j20 -l30 concurrent-linkers=2


Basically, it separates the build in two make invocations, one for compilation and one for link, with different -j options. The main drawback is that all compilations must be finished before the first link starts. A better solution would be to design a simple link job server (a simple shell script with a bit of flock and tag files would make it) and delegate it the link jobs. But if you can live with this...



Demo with a dummy Makefile:



$ cat Makefile
OBJS := a b c d e f
EXES := u v w x y z

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS) $(EXES):
@printf 'building $@...n' && sleep 2 && printf 'donen' && touch $@
$ make -j20 -l30 concurrent-linkers=2
building a...
building d...
building b...
building c...
building e...
building f...
done
done
done
done
done
done
make -j 2 u v w x y z
make[1]: warning: -jN forced in submake: disabling jobserver mode.
make[1]: Entering directory 'foobar'
building u...
building v...
done
done
building w...
building x...
done
done
building y...
building z...
done
done
make[1]: Leaving directory 'foobar'


As you can see all $(OBJS) targets are built in parallel while the $(EXES) targets are built 2 (maximum) at a time.



EDIT If your makefile is generated by CMake there are at least two options:




  1. Tune your CMake files such that CMake generates two different makefiles: one for compilation and one for link. Then write a simple wrapper makefile like:



    .PHONY: myAll myCompile

    myAll: myCompile
    $(MAKE) -j $(concurrent-linkers) -f Makefile.link

    myCompile:
    $(MAKE) -f Makefile.compilation



  2. Convince CMake (if it is not already the case) to generate a makefile that defines two make variables: one (OBJS) set to the list of all object files and one (EXES) set to the list of all executable. Then write a simple wrapper makefile like:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: $(OBJS)
    $(MAKE) -j $(concurrent-linkers) $(EXES)


    A very similar solution exists if, instead, CMake generates two phony targets, one for all object files and the other for all executable:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: cmake-target-for-compilation
    $(MAKE) -j $(concurrent-linkers) cmake-target-for-link






share|improve this answer

























  • The Makefile in the question is generated by CMake; this answer presumes a hand-rolled Makefile.

    – MSalters
    Mar 7 at 13:40











  • MSalters is correct - is it possible to do with CMake?

    – MateuszL
    Mar 7 at 14:06











  • If you can use CMake to generate two makefiles, one for compilation and one for link, then yes, it is possible (and easy). Else, you must find a way to tell CMake that you want a makefile that defines a make variable set to all object files and another set to all executable. You will then simply include this CMake-generated makefile in a wrapper makefile that does more or less what I suggest in my examples.

    – Renaud Pacalet
    Mar 7 at 14:19










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55039722%2fcompile-concurrently-link-serially%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














You could try something like:



$ cat Makefile
OBJS := foo bar baz...
EXES := qux quux quuz...

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS): ...
<compile>

$(EXES): ...
<link>


And call it with:



$ make -j20 -l30 concurrent-linkers=2


Basically, it separates the build in two make invocations, one for compilation and one for link, with different -j options. The main drawback is that all compilations must be finished before the first link starts. A better solution would be to design a simple link job server (a simple shell script with a bit of flock and tag files would make it) and delegate it the link jobs. But if you can live with this...



Demo with a dummy Makefile:



$ cat Makefile
OBJS := a b c d e f
EXES := u v w x y z

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS) $(EXES):
@printf 'building $@...n' && sleep 2 && printf 'donen' && touch $@
$ make -j20 -l30 concurrent-linkers=2
building a...
building d...
building b...
building c...
building e...
building f...
done
done
done
done
done
done
make -j 2 u v w x y z
make[1]: warning: -jN forced in submake: disabling jobserver mode.
make[1]: Entering directory 'foobar'
building u...
building v...
done
done
building w...
building x...
done
done
building y...
building z...
done
done
make[1]: Leaving directory 'foobar'


As you can see all $(OBJS) targets are built in parallel while the $(EXES) targets are built 2 (maximum) at a time.



EDIT If your makefile is generated by CMake there are at least two options:




  1. Tune your CMake files such that CMake generates two different makefiles: one for compilation and one for link. Then write a simple wrapper makefile like:



    .PHONY: myAll myCompile

    myAll: myCompile
    $(MAKE) -j $(concurrent-linkers) -f Makefile.link

    myCompile:
    $(MAKE) -f Makefile.compilation



  2. Convince CMake (if it is not already the case) to generate a makefile that defines two make variables: one (OBJS) set to the list of all object files and one (EXES) set to the list of all executable. Then write a simple wrapper makefile like:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: $(OBJS)
    $(MAKE) -j $(concurrent-linkers) $(EXES)


    A very similar solution exists if, instead, CMake generates two phony targets, one for all object files and the other for all executable:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: cmake-target-for-compilation
    $(MAKE) -j $(concurrent-linkers) cmake-target-for-link






share|improve this answer

























  • The Makefile in the question is generated by CMake; this answer presumes a hand-rolled Makefile.

    – MSalters
    Mar 7 at 13:40











  • MSalters is correct - is it possible to do with CMake?

    – MateuszL
    Mar 7 at 14:06











  • If you can use CMake to generate two makefiles, one for compilation and one for link, then yes, it is possible (and easy). Else, you must find a way to tell CMake that you want a makefile that defines a make variable set to all object files and another set to all executable. You will then simply include this CMake-generated makefile in a wrapper makefile that does more or less what I suggest in my examples.

    – Renaud Pacalet
    Mar 7 at 14:19















0














You could try something like:



$ cat Makefile
OBJS := foo bar baz...
EXES := qux quux quuz...

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS): ...
<compile>

$(EXES): ...
<link>


And call it with:



$ make -j20 -l30 concurrent-linkers=2


Basically, it separates the build in two make invocations, one for compilation and one for link, with different -j options. The main drawback is that all compilations must be finished before the first link starts. A better solution would be to design a simple link job server (a simple shell script with a bit of flock and tag files would make it) and delegate it the link jobs. But if you can live with this...



Demo with a dummy Makefile:



$ cat Makefile
OBJS := a b c d e f
EXES := u v w x y z

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS) $(EXES):
@printf 'building $@...n' && sleep 2 && printf 'donen' && touch $@
$ make -j20 -l30 concurrent-linkers=2
building a...
building d...
building b...
building c...
building e...
building f...
done
done
done
done
done
done
make -j 2 u v w x y z
make[1]: warning: -jN forced in submake: disabling jobserver mode.
make[1]: Entering directory 'foobar'
building u...
building v...
done
done
building w...
building x...
done
done
building y...
building z...
done
done
make[1]: Leaving directory 'foobar'


As you can see all $(OBJS) targets are built in parallel while the $(EXES) targets are built 2 (maximum) at a time.



EDIT If your makefile is generated by CMake there are at least two options:




  1. Tune your CMake files such that CMake generates two different makefiles: one for compilation and one for link. Then write a simple wrapper makefile like:



    .PHONY: myAll myCompile

    myAll: myCompile
    $(MAKE) -j $(concurrent-linkers) -f Makefile.link

    myCompile:
    $(MAKE) -f Makefile.compilation



  2. Convince CMake (if it is not already the case) to generate a makefile that defines two make variables: one (OBJS) set to the list of all object files and one (EXES) set to the list of all executable. Then write a simple wrapper makefile like:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: $(OBJS)
    $(MAKE) -j $(concurrent-linkers) $(EXES)


    A very similar solution exists if, instead, CMake generates two phony targets, one for all object files and the other for all executable:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: cmake-target-for-compilation
    $(MAKE) -j $(concurrent-linkers) cmake-target-for-link






share|improve this answer

























  • The Makefile in the question is generated by CMake; this answer presumes a hand-rolled Makefile.

    – MSalters
    Mar 7 at 13:40











  • MSalters is correct - is it possible to do with CMake?

    – MateuszL
    Mar 7 at 14:06











  • If you can use CMake to generate two makefiles, one for compilation and one for link, then yes, it is possible (and easy). Else, you must find a way to tell CMake that you want a makefile that defines a make variable set to all object files and another set to all executable. You will then simply include this CMake-generated makefile in a wrapper makefile that does more or less what I suggest in my examples.

    – Renaud Pacalet
    Mar 7 at 14:19













0












0








0







You could try something like:



$ cat Makefile
OBJS := foo bar baz...
EXES := qux quux quuz...

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS): ...
<compile>

$(EXES): ...
<link>


And call it with:



$ make -j20 -l30 concurrent-linkers=2


Basically, it separates the build in two make invocations, one for compilation and one for link, with different -j options. The main drawback is that all compilations must be finished before the first link starts. A better solution would be to design a simple link job server (a simple shell script with a bit of flock and tag files would make it) and delegate it the link jobs. But if you can live with this...



Demo with a dummy Makefile:



$ cat Makefile
OBJS := a b c d e f
EXES := u v w x y z

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS) $(EXES):
@printf 'building $@...n' && sleep 2 && printf 'donen' && touch $@
$ make -j20 -l30 concurrent-linkers=2
building a...
building d...
building b...
building c...
building e...
building f...
done
done
done
done
done
done
make -j 2 u v w x y z
make[1]: warning: -jN forced in submake: disabling jobserver mode.
make[1]: Entering directory 'foobar'
building u...
building v...
done
done
building w...
building x...
done
done
building y...
building z...
done
done
make[1]: Leaving directory 'foobar'


As you can see all $(OBJS) targets are built in parallel while the $(EXES) targets are built 2 (maximum) at a time.



EDIT If your makefile is generated by CMake there are at least two options:




  1. Tune your CMake files such that CMake generates two different makefiles: one for compilation and one for link. Then write a simple wrapper makefile like:



    .PHONY: myAll myCompile

    myAll: myCompile
    $(MAKE) -j $(concurrent-linkers) -f Makefile.link

    myCompile:
    $(MAKE) -f Makefile.compilation



  2. Convince CMake (if it is not already the case) to generate a makefile that defines two make variables: one (OBJS) set to the list of all object files and one (EXES) set to the list of all executable. Then write a simple wrapper makefile like:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: $(OBJS)
    $(MAKE) -j $(concurrent-linkers) $(EXES)


    A very similar solution exists if, instead, CMake generates two phony targets, one for all object files and the other for all executable:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: cmake-target-for-compilation
    $(MAKE) -j $(concurrent-linkers) cmake-target-for-link






share|improve this answer















You could try something like:



$ cat Makefile
OBJS := foo bar baz...
EXES := qux quux quuz...

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS): ...
<compile>

$(EXES): ...
<link>


And call it with:



$ make -j20 -l30 concurrent-linkers=2


Basically, it separates the build in two make invocations, one for compilation and one for link, with different -j options. The main drawback is that all compilations must be finished before the first link starts. A better solution would be to design a simple link job server (a simple shell script with a bit of flock and tag files would make it) and delegate it the link jobs. But if you can live with this...



Demo with a dummy Makefile:



$ cat Makefile
OBJS := a b c d e f
EXES := u v w x y z

.PHONY: all

all: $(OBJS)
$(MAKE) -j $(concurrent-linkers) $(EXES)

$(OBJS) $(EXES):
@printf 'building $@...n' && sleep 2 && printf 'donen' && touch $@
$ make -j20 -l30 concurrent-linkers=2
building a...
building d...
building b...
building c...
building e...
building f...
done
done
done
done
done
done
make -j 2 u v w x y z
make[1]: warning: -jN forced in submake: disabling jobserver mode.
make[1]: Entering directory 'foobar'
building u...
building v...
done
done
building w...
building x...
done
done
building y...
building z...
done
done
make[1]: Leaving directory 'foobar'


As you can see all $(OBJS) targets are built in parallel while the $(EXES) targets are built 2 (maximum) at a time.



EDIT If your makefile is generated by CMake there are at least two options:




  1. Tune your CMake files such that CMake generates two different makefiles: one for compilation and one for link. Then write a simple wrapper makefile like:



    .PHONY: myAll myCompile

    myAll: myCompile
    $(MAKE) -j $(concurrent-linkers) -f Makefile.link

    myCompile:
    $(MAKE) -f Makefile.compilation



  2. Convince CMake (if it is not already the case) to generate a makefile that defines two make variables: one (OBJS) set to the list of all object files and one (EXES) set to the list of all executable. Then write a simple wrapper makefile like:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: $(OBJS)
    $(MAKE) -j $(concurrent-linkers) $(EXES)


    A very similar solution exists if, instead, CMake generates two phony targets, one for all object files and the other for all executable:



    .DEFAULT_GOAL := myAll

    include CMake.generated.Makefile

    .PHONY: myAll

    myAll: cmake-target-for-compilation
    $(MAKE) -j $(concurrent-linkers) cmake-target-for-link







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 7 at 14:44

























answered Mar 7 at 12:35









Renaud PacaletRenaud Pacalet

9,60821731




9,60821731












  • The Makefile in the question is generated by CMake; this answer presumes a hand-rolled Makefile.

    – MSalters
    Mar 7 at 13:40











  • MSalters is correct - is it possible to do with CMake?

    – MateuszL
    Mar 7 at 14:06











  • If you can use CMake to generate two makefiles, one for compilation and one for link, then yes, it is possible (and easy). Else, you must find a way to tell CMake that you want a makefile that defines a make variable set to all object files and another set to all executable. You will then simply include this CMake-generated makefile in a wrapper makefile that does more or less what I suggest in my examples.

    – Renaud Pacalet
    Mar 7 at 14:19

















  • The Makefile in the question is generated by CMake; this answer presumes a hand-rolled Makefile.

    – MSalters
    Mar 7 at 13:40











  • MSalters is correct - is it possible to do with CMake?

    – MateuszL
    Mar 7 at 14:06











  • If you can use CMake to generate two makefiles, one for compilation and one for link, then yes, it is possible (and easy). Else, you must find a way to tell CMake that you want a makefile that defines a make variable set to all object files and another set to all executable. You will then simply include this CMake-generated makefile in a wrapper makefile that does more or less what I suggest in my examples.

    – Renaud Pacalet
    Mar 7 at 14:19
















The Makefile in the question is generated by CMake; this answer presumes a hand-rolled Makefile.

– MSalters
Mar 7 at 13:40





The Makefile in the question is generated by CMake; this answer presumes a hand-rolled Makefile.

– MSalters
Mar 7 at 13:40













MSalters is correct - is it possible to do with CMake?

– MateuszL
Mar 7 at 14:06





MSalters is correct - is it possible to do with CMake?

– MateuszL
Mar 7 at 14:06













If you can use CMake to generate two makefiles, one for compilation and one for link, then yes, it is possible (and easy). Else, you must find a way to tell CMake that you want a makefile that defines a make variable set to all object files and another set to all executable. You will then simply include this CMake-generated makefile in a wrapper makefile that does more or less what I suggest in my examples.

– Renaud Pacalet
Mar 7 at 14:19





If you can use CMake to generate two makefiles, one for compilation and one for link, then yes, it is possible (and easy). Else, you must find a way to tell CMake that you want a makefile that defines a make variable set to all object files and another set to all executable. You will then simply include this CMake-generated makefile in a wrapper makefile that does more or less what I suggest in my examples.

– Renaud Pacalet
Mar 7 at 14:19



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55039722%2fcompile-concurrently-link-serially%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

AWS Lex not identifying response if by a variable The 2019 Stack Overflow Developer Survey Results Are In Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 17/18, 2019 at 00:00UTC (8:00pm US/Eastern) The Ask Question Wizard is Live! Data science time! April 2019 and salary with experienceEnforcing custom enumeration in AWS LEX for slot valuesHow to give response based on user response in Amazon Lex?Intercepting AWS Lambda Response to a AWS Lex QueryLex chat bot error: Reached second execution of fulfillment lambda on the same utteranceamazon lex showing invalid responseLambda response send back to Lex slot?Response card in Amazon lexAmazon Lex - Lambda response return HTML to botHow can I solve 424 (Failed Dependency) (python) obtained from Amazon lex?

Алба-Юлія

Захаров Федір Захарович