Reputation: 6561
I have a simple .cpp
file that depends on jsoncpp
. As a part of my build process I want Scons to untar jsoncpp (if it isn't already) and build it (if it isn't already) before attempting to compile app.cpp
since app.cpp
depends on some .h
files that are zipped up inside of jsoncpp.tar.gz
.
This is what I've tried so far:
env = Environment()
env.Program('app', 'app.cpp')
env.Depends('app.cpp', 'jsoncpp')
def build_jsoncpp(target, source, env):
shutil.rmtree("jsoncpp", ignore_errors=True)
mytar = tarfile.open(str(source[0]))
mytar.extractall()
print("Extracted jsoncpp")
env.Command("jsoncpp", ['jsoncpp.tar.gz'], build_jsoncpp)
However, Scons never prints "Extracted jsoncpp"... it always attempts to compile app.cpp and then promptly fails.
If I were using make
, I could simply do something like:
app: jsoncpp.tar.gz
# Build app
jsoncpp.tar.gz:
# Extract and build here
And the order would be guaranteed.
Upvotes: 2
Views: 1659
Reputation: 1056
You should take a look at the UnTarBuilder, as a means to extract a tarfile and have all of the extracted files be properly inserted into the dependency tree. But the following will get what you have working.
You want to avoid explicit dependencies, if possible. One of the many joys of SCons is letting it take care of your dependencies for you. So just list the source file you are depending on as one of the targets of your untar command builder.
To test this I created a tar file called jsoncpp.tar.gz
containing just one file, app.cpp
, with the following contents.
#include <iostream>
int main() {
std::cout << "Hello World" << std::endl;
return 0;
}
And updated your SConstruct to the following.
import shutil
import tarfile
env = Environment()
env.Program('app', 'app.cpp')
def build_jsoncpp(target, source, env):
shutil.rmtree("jsoncpp", ignore_errors=True)
mytar = tarfile.open(str(source[0]))
mytar.extractall()
print("Extracted jsoncpp")
env.Command(["app.cpp"], ['jsoncpp.tar.gz'], build_jsoncpp)
Because you list the required source file you depend on as a target of your command builder, it will handle the dependencies for you.
And when you run, you will see the following.
>> scons --version
SCons by Steven Knight et al.:
script: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine: v2.3.4, 2014/09/27 12:51:43, by garyo on lubuntu
engine path: ['/usr/lib/scons/SCons']
Copyright (c) 2001 - 2014 The SCons Foundation
>> tree
.
├── jsoncpp.tar.gz
└── SConstruct
0 directories, 2 files
>> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
build_jsoncpp(["app.cpp"], ["jsoncpp.tar.gz"])
Extracted jsoncpp
g++ -o app.o -c app.cpp
g++ -o app app.o
scons: done building targets.
>> tree
.
├── app
├── app.cpp
├── app.o
├── jsoncpp.tar.gz
└── SConstruct
0 directories, 5 files
>> ./app
Hello World
The reason why your code does not work is because you are listing jsoncpp
as the target of your untar command builder. Which is not a file that compiling app.cpp
will depend on, even if you list that action as an explicit dependency.
While this doesn't exactly answer your question, I hope it provides a solution to what you are trying to accomplish.
Upvotes: 2
Reputation: 4052
It might help if you aligned the name of your builder function with your argument to the Command() method. ;)
Upvotes: 0