Running compilation scripts only if the source file is more recent than the compiled program
I am trying to do is create a bash script that will run another bash script to compile some programs only if the source has changed. What I have so far is a way to get the timestamps for each file in seconds since J2000 epoch:
#get a list of the source timestamps
sourceTimes=$(stat -f "%Sm" -t "%s" *.f)
#get a list of the program timestamps
exeTimes=$(stat -f "%Sm" -t "%s")
and an install script
./make_common_lib.bsh build
./make_common_lib.bsh install
I want to figure out how to create an if state such that (in semi-pseudocode)
if [any of $sourceTimes>$exeTimes];
then #run make_common_lib.bsh script
else #Do nothing
fi
My best guess so far is to somehow use read
but I am not sure how I could index both variables at the same time.
If there is a really easy way to do this I apologize as I am very new to bash scripting, but so far none of my google searches have really returned anything useful.
Some more information:
The timestamp variables are in a format like
1432326068 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326068 1432326069 1432326069
bash shell-script timestamps
add a comment |
I am trying to do is create a bash script that will run another bash script to compile some programs only if the source has changed. What I have so far is a way to get the timestamps for each file in seconds since J2000 epoch:
#get a list of the source timestamps
sourceTimes=$(stat -f "%Sm" -t "%s" *.f)
#get a list of the program timestamps
exeTimes=$(stat -f "%Sm" -t "%s")
and an install script
./make_common_lib.bsh build
./make_common_lib.bsh install
I want to figure out how to create an if state such that (in semi-pseudocode)
if [any of $sourceTimes>$exeTimes];
then #run make_common_lib.bsh script
else #Do nothing
fi
My best guess so far is to somehow use read
but I am not sure how I could index both variables at the same time.
If there is a really easy way to do this I apologize as I am very new to bash scripting, but so far none of my google searches have really returned anything useful.
Some more information:
The timestamp variables are in a format like
1432326068 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326068 1432326069 1432326069
bash shell-script timestamps
3
Why not usemake
? It is explicitly designed to handle this requirement.
– Stephen Kitt
Aug 4 '15 at 16:11
I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
– Andrew
Aug 4 '15 at 16:26
That's what wildcards are for.
– bahamat
Aug 4 '15 at 19:58
@Andrew What people usually do is to automatically generate the list of dependencies (usually you runmake depend
ormake dep
to regenerate the list).
– Gilles
Aug 4 '15 at 23:10
add a comment |
I am trying to do is create a bash script that will run another bash script to compile some programs only if the source has changed. What I have so far is a way to get the timestamps for each file in seconds since J2000 epoch:
#get a list of the source timestamps
sourceTimes=$(stat -f "%Sm" -t "%s" *.f)
#get a list of the program timestamps
exeTimes=$(stat -f "%Sm" -t "%s")
and an install script
./make_common_lib.bsh build
./make_common_lib.bsh install
I want to figure out how to create an if state such that (in semi-pseudocode)
if [any of $sourceTimes>$exeTimes];
then #run make_common_lib.bsh script
else #Do nothing
fi
My best guess so far is to somehow use read
but I am not sure how I could index both variables at the same time.
If there is a really easy way to do this I apologize as I am very new to bash scripting, but so far none of my google searches have really returned anything useful.
Some more information:
The timestamp variables are in a format like
1432326068 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326068 1432326069 1432326069
bash shell-script timestamps
I am trying to do is create a bash script that will run another bash script to compile some programs only if the source has changed. What I have so far is a way to get the timestamps for each file in seconds since J2000 epoch:
#get a list of the source timestamps
sourceTimes=$(stat -f "%Sm" -t "%s" *.f)
#get a list of the program timestamps
exeTimes=$(stat -f "%Sm" -t "%s")
and an install script
./make_common_lib.bsh build
./make_common_lib.bsh install
I want to figure out how to create an if state such that (in semi-pseudocode)
if [any of $sourceTimes>$exeTimes];
then #run make_common_lib.bsh script
else #Do nothing
fi
My best guess so far is to somehow use read
but I am not sure how I could index both variables at the same time.
If there is a really easy way to do this I apologize as I am very new to bash scripting, but so far none of my google searches have really returned anything useful.
Some more information:
The timestamp variables are in a format like
1432326068 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326069 1432326068 1432326069 1432326069
bash shell-script timestamps
bash shell-script timestamps
edited 2 days ago
Rui F Ribeiro
39.3k1479131
39.3k1479131
asked Aug 4 '15 at 15:45
AndrewAndrew
1183
1183
3
Why not usemake
? It is explicitly designed to handle this requirement.
– Stephen Kitt
Aug 4 '15 at 16:11
I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
– Andrew
Aug 4 '15 at 16:26
That's what wildcards are for.
– bahamat
Aug 4 '15 at 19:58
@Andrew What people usually do is to automatically generate the list of dependencies (usually you runmake depend
ormake dep
to regenerate the list).
– Gilles
Aug 4 '15 at 23:10
add a comment |
3
Why not usemake
? It is explicitly designed to handle this requirement.
– Stephen Kitt
Aug 4 '15 at 16:11
I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
– Andrew
Aug 4 '15 at 16:26
That's what wildcards are for.
– bahamat
Aug 4 '15 at 19:58
@Andrew What people usually do is to automatically generate the list of dependencies (usually you runmake depend
ormake dep
to regenerate the list).
– Gilles
Aug 4 '15 at 23:10
3
3
Why not use
make
? It is explicitly designed to handle this requirement.– Stephen Kitt
Aug 4 '15 at 16:11
Why not use
make
? It is explicitly designed to handle this requirement.– Stephen Kitt
Aug 4 '15 at 16:11
I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
– Andrew
Aug 4 '15 at 16:26
I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
– Andrew
Aug 4 '15 at 16:26
That's what wildcards are for.
– bahamat
Aug 4 '15 at 19:58
That's what wildcards are for.
– bahamat
Aug 4 '15 at 19:58
@Andrew What people usually do is to automatically generate the list of dependencies (usually you run
make depend
or make dep
to regenerate the list).– Gilles
Aug 4 '15 at 23:10
@Andrew What people usually do is to automatically generate the list of dependencies (usually you run
make depend
or make dep
to regenerate the list).– Gilles
Aug 4 '15 at 23:10
add a comment |
1 Answer
1
active
oldest
votes
Your Build Script Method
If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild
) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find
to see if any newer files exist:
find . -name "*.[ch]" -newer lastbuild
and then build if that output is 1 or more lines (could be checked with something like wc -l
).
Using Make instead
This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).
default: all
all: dependency1.o dependency2.o
dependency1.o: dependency1.c
./make_common_lib.bsh build
dependency2.o: dependency2.c
./make_common_lib.bsh build
install:
./make_common_lib.bsh install
Creating a dummy "build" script:
$ cat make_common_lib.bsh
#! /bin/sh
echo "Build $1"
We can now run make:
$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build
You could also replace the ./make_common_lib.bsh build
with the command that ./make_common_lib.bsh build
would issue to build dependency1.o
etc:
dependency1.o: dependency1.c
gcc -c dependency1.c
Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:
CC=/usr/bin/gcc
CFLAGS=-O2 -Wall
and then make references to them in your rules:
dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c
Note that the line that is indented after a dependency declaration must start with a tab and not spaces.
Shortening dependency rules list
The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).
You can do variable substitution. Given the declaration:
SRCS=dependency1.c dependency2.c dependency3.c
You can then create an objects rule using variable substitution:
OBJS=$(SRCS:.c=.o)
this will replace all .c
's with .o
's. In effect giving a line of the form:
OBJS=dependency1.o dependency2.o dependency3.o
You can then further do a shortening of the "compile command" using the special variables $<
and $@
:
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
$<
represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@
the target, and so it will end up issuing:
/usr/bin/gcc -Wall -O2 -c dependency1.c -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.
Putting this all together, with linking options and a command to link and compile the executable $(TARGET)
:
# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib
# declare all the sources
SRCS=dependency1.c dependency2.c
# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)
# Target executable name:
TARGET=myexefile
default: all
all: $(TARGET)
@echo Target has been built
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
install:
./make_common_lib.bsh install
Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.
thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
– Andrew
Aug 4 '15 at 16:25
I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
– Drav Sloan
Aug 4 '15 at 17:00
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
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: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f220168%2frunning-compilation-scripts-only-if-the-source-file-is-more-recent-than-the-comp%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
Your Build Script Method
If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild
) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find
to see if any newer files exist:
find . -name "*.[ch]" -newer lastbuild
and then build if that output is 1 or more lines (could be checked with something like wc -l
).
Using Make instead
This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).
default: all
all: dependency1.o dependency2.o
dependency1.o: dependency1.c
./make_common_lib.bsh build
dependency2.o: dependency2.c
./make_common_lib.bsh build
install:
./make_common_lib.bsh install
Creating a dummy "build" script:
$ cat make_common_lib.bsh
#! /bin/sh
echo "Build $1"
We can now run make:
$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build
You could also replace the ./make_common_lib.bsh build
with the command that ./make_common_lib.bsh build
would issue to build dependency1.o
etc:
dependency1.o: dependency1.c
gcc -c dependency1.c
Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:
CC=/usr/bin/gcc
CFLAGS=-O2 -Wall
and then make references to them in your rules:
dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c
Note that the line that is indented after a dependency declaration must start with a tab and not spaces.
Shortening dependency rules list
The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).
You can do variable substitution. Given the declaration:
SRCS=dependency1.c dependency2.c dependency3.c
You can then create an objects rule using variable substitution:
OBJS=$(SRCS:.c=.o)
this will replace all .c
's with .o
's. In effect giving a line of the form:
OBJS=dependency1.o dependency2.o dependency3.o
You can then further do a shortening of the "compile command" using the special variables $<
and $@
:
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
$<
represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@
the target, and so it will end up issuing:
/usr/bin/gcc -Wall -O2 -c dependency1.c -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.
Putting this all together, with linking options and a command to link and compile the executable $(TARGET)
:
# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib
# declare all the sources
SRCS=dependency1.c dependency2.c
# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)
# Target executable name:
TARGET=myexefile
default: all
all: $(TARGET)
@echo Target has been built
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
install:
./make_common_lib.bsh install
Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.
thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
– Andrew
Aug 4 '15 at 16:25
I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
– Drav Sloan
Aug 4 '15 at 17:00
add a comment |
Your Build Script Method
If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild
) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find
to see if any newer files exist:
find . -name "*.[ch]" -newer lastbuild
and then build if that output is 1 or more lines (could be checked with something like wc -l
).
Using Make instead
This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).
default: all
all: dependency1.o dependency2.o
dependency1.o: dependency1.c
./make_common_lib.bsh build
dependency2.o: dependency2.c
./make_common_lib.bsh build
install:
./make_common_lib.bsh install
Creating a dummy "build" script:
$ cat make_common_lib.bsh
#! /bin/sh
echo "Build $1"
We can now run make:
$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build
You could also replace the ./make_common_lib.bsh build
with the command that ./make_common_lib.bsh build
would issue to build dependency1.o
etc:
dependency1.o: dependency1.c
gcc -c dependency1.c
Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:
CC=/usr/bin/gcc
CFLAGS=-O2 -Wall
and then make references to them in your rules:
dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c
Note that the line that is indented after a dependency declaration must start with a tab and not spaces.
Shortening dependency rules list
The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).
You can do variable substitution. Given the declaration:
SRCS=dependency1.c dependency2.c dependency3.c
You can then create an objects rule using variable substitution:
OBJS=$(SRCS:.c=.o)
this will replace all .c
's with .o
's. In effect giving a line of the form:
OBJS=dependency1.o dependency2.o dependency3.o
You can then further do a shortening of the "compile command" using the special variables $<
and $@
:
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
$<
represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@
the target, and so it will end up issuing:
/usr/bin/gcc -Wall -O2 -c dependency1.c -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.
Putting this all together, with linking options and a command to link and compile the executable $(TARGET)
:
# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib
# declare all the sources
SRCS=dependency1.c dependency2.c
# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)
# Target executable name:
TARGET=myexefile
default: all
all: $(TARGET)
@echo Target has been built
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
install:
./make_common_lib.bsh install
Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.
thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
– Andrew
Aug 4 '15 at 16:25
I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
– Drav Sloan
Aug 4 '15 at 17:00
add a comment |
Your Build Script Method
If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild
) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find
to see if any newer files exist:
find . -name "*.[ch]" -newer lastbuild
and then build if that output is 1 or more lines (could be checked with something like wc -l
).
Using Make instead
This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).
default: all
all: dependency1.o dependency2.o
dependency1.o: dependency1.c
./make_common_lib.bsh build
dependency2.o: dependency2.c
./make_common_lib.bsh build
install:
./make_common_lib.bsh install
Creating a dummy "build" script:
$ cat make_common_lib.bsh
#! /bin/sh
echo "Build $1"
We can now run make:
$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build
You could also replace the ./make_common_lib.bsh build
with the command that ./make_common_lib.bsh build
would issue to build dependency1.o
etc:
dependency1.o: dependency1.c
gcc -c dependency1.c
Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:
CC=/usr/bin/gcc
CFLAGS=-O2 -Wall
and then make references to them in your rules:
dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c
Note that the line that is indented after a dependency declaration must start with a tab and not spaces.
Shortening dependency rules list
The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).
You can do variable substitution. Given the declaration:
SRCS=dependency1.c dependency2.c dependency3.c
You can then create an objects rule using variable substitution:
OBJS=$(SRCS:.c=.o)
this will replace all .c
's with .o
's. In effect giving a line of the form:
OBJS=dependency1.o dependency2.o dependency3.o
You can then further do a shortening of the "compile command" using the special variables $<
and $@
:
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
$<
represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@
the target, and so it will end up issuing:
/usr/bin/gcc -Wall -O2 -c dependency1.c -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.
Putting this all together, with linking options and a command to link and compile the executable $(TARGET)
:
# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib
# declare all the sources
SRCS=dependency1.c dependency2.c
# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)
# Target executable name:
TARGET=myexefile
default: all
all: $(TARGET)
@echo Target has been built
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
install:
./make_common_lib.bsh install
Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.
Your Build Script Method
If you want to keep to the "bash build method", then you are probably best off "touching" a file (touch lastbuild
) when the build script is ran and completes the build. In addition the build script could then look for the file generated by touch (if it doesn't exist, assume a build is needed), or if it exists use find
to see if any newer files exist:
find . -name "*.[ch]" -newer lastbuild
and then build if that output is 1 or more lines (could be checked with something like wc -l
).
Using Make instead
This is best managed by something like a Makefile (specifically used to do this kind of dependency checking).
default: all
all: dependency1.o dependency2.o
dependency1.o: dependency1.c
./make_common_lib.bsh build
dependency2.o: dependency2.c
./make_common_lib.bsh build
install:
./make_common_lib.bsh install
Creating a dummy "build" script:
$ cat make_common_lib.bsh
#! /bin/sh
echo "Build $1"
We can now run make:
$ make
./make_common_lib.bsh build
Build build
./make_common_lib.bsh build
Build build
You could also replace the ./make_common_lib.bsh build
with the command that ./make_common_lib.bsh build
would issue to build dependency1.o
etc:
dependency1.o: dependency1.c
gcc -c dependency1.c
Makefiles also allow for symbol substitution, so you could declare the complier and compiler flags earlier in the Makefile:
CC=/usr/bin/gcc
CFLAGS=-O2 -Wall
and then make references to them in your rules:
dependency1.o: dependency1.c
$(CC) $(CFLAGS) -c dependency1.c
Note that the line that is indented after a dependency declaration must start with a tab and not spaces.
Shortening dependency rules list
The OP asked if it's possible to do shorter ways of declaring all dependencies. It is possible with a few tricks using GNU's make (note not all these will work with vanilla make).
You can do variable substitution. Given the declaration:
SRCS=dependency1.c dependency2.c dependency3.c
You can then create an objects rule using variable substitution:
OBJS=$(SRCS:.c=.o)
this will replace all .c
's with .o
's. In effect giving a line of the form:
OBJS=dependency1.o dependency2.o dependency3.o
You can then further do a shortening of the "compile command" using the special variables $<
and $@
:
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
$<
represents the prerequisite in GNU make parlance (or dependency as I've called it) and $@
the target, and so it will end up issuing:
/usr/bin/gcc -Wall -O2 -c dependency1.c -o dependency1.o
/usr/bin/gcc -Wall -O2 -c dependency2.c -o dependency2.o
.
.
.
Putting this all together, with linking options and a command to link and compile the executable $(TARGET)
:
# Globals
CC=/usr/bin/gcc
CFLAGS=-Wall -O2
LDFLAGS=-L/usr/local/lib
LIBS=-ldependencylib
# declare all the sources
SRCS=dependency1.c dependency2.c
# declare the objects files using variable substitution (find .c and replace with .o)
OBJS=$(SRCS:.c=.o)
# Target executable name:
TARGET=myexefile
default: all
all: $(TARGET)
@echo Target has been built
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) $(LIBS)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
install:
./make_common_lib.bsh install
Note that there are many things you can do with GNU make, and it is well documented here GNU Make Manual.
edited Aug 4 '15 at 18:17
answered Aug 4 '15 at 16:18
Drav SloanDrav Sloan
9,61023138
9,61023138
thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
– Andrew
Aug 4 '15 at 16:25
I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
– Drav Sloan
Aug 4 '15 at 17:00
add a comment |
thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
– Andrew
Aug 4 '15 at 16:25
I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
– Drav Sloan
Aug 4 '15 at 17:00
thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
– Andrew
Aug 4 '15 at 16:25
thanks for the response. I wish that the people who originally designed this software had done a straight up make file but they haven't. One question I have is, is there someway to do this without having to write out each dependency? There are over 100 separate files that need to be checked and I don't really want to have to write out a dependency for each one.
– Andrew
Aug 4 '15 at 16:25
I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
– Drav Sloan
Aug 4 '15 at 17:00
I've updated the answer to use some GNU make shortcuts to handle multiple dependencies.
– Drav Sloan
Aug 4 '15 at 17:00
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- 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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f220168%2frunning-compilation-scripts-only-if-the-source-file-is-more-recent-than-the-comp%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
3
Why not use
make
? It is explicitly designed to handle this requirement.– Stephen Kitt
Aug 4 '15 at 16:11
I do realize this but I'm actually working with someone else's program and for some reason they didn't use make. The problem with make (I think) is that I would need to write out each dependency and there are more than 100 in the common libraries alone (and there's an entire other group of files that I would have to do the same thing for).
– Andrew
Aug 4 '15 at 16:26
That's what wildcards are for.
– bahamat
Aug 4 '15 at 19:58
@Andrew What people usually do is to automatically generate the list of dependencies (usually you run
make depend
ormake dep
to regenerate the list).– Gilles
Aug 4 '15 at 23:10