It's often useful to be able to run "scons install" to copy the programs and shared libraries to their correct locations. Here's one way to do that:
1 prefix = "/usr/local"
2
3 someshlib = env.SharedLibrary('foo', "foo.c")
4 someprogram = env.Program("fooprog", "fooprog.c")
5
6 # the install target
7 env.Alias("install", env.Install(os.path.join(prefix, "lib"), someshlib))
8 env.Alias("install", env.Install(os.path.join(prefix, "bin"), someprogram))
Basically we alias 'install' to a couple of Install nodes, returned by the Install() method. That's all.
NB: There is no need to add something like 'Depends(install, someshlib)', since SCons does find this dependency automatically.
If you need some fine-grained install targets, you may use something like this:
Permissions
Question: how to set permissions properly (binaries get 755, headers get 644, etc.) after an install?
- One way to do it is to create a method that acts like Install() but has an additional permission argument. Wrappers with predefined permissions are useful for cleaner markup:
1 import SCons
2
3 # define the custom function
4 from SCons.Script.SConscript import SConsEnvironment
5 SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod,
6 lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode))
7
8 def InstallPerm(env, dest, files, perm):
9 obj = env.Install(dest, files)
10 for i in obj:
11 env.AddPostAction(i, env.Chmod(str(i), perm))
12 return dest
13
14 # put this function "in" scons
15 SConsEnvironment.InstallPerm = InstallPerm
16
17 # great, we're ready to use it!
18 env.InstallPerm(bindir, ['fooprog', 'barprog'], 0755)
19
20 # but let's say we're not happy yet, we'd prefer nicer names.
21 SConsEnvironment.InstallProgram = lambda env, dest, files: InstallPerm(env, dest, files, 0755)
22 SConsEnvironment.InstallHeader = lambda env, dest, files: InstallPerm(env, dest, files, 0644)
23
24 # great, now you can also install by calling a method named 'InstallHeader' or 'InstallProgram'!
25 env.InstallHeader(incdir, ['foo.h', 'bar.h'])
Don't forget to set the umask, or created directories might get wrong permissions on Unix and Windows:
- Another similar method to install data with correct permissions is to use a Command :
where target and source could be set in a directory parsing loop for conveniance :
1 # where you need to implement 'RecursiveGlob' yourself
2 for file in RecursiveGlob("./data", "*"):
3 # strip 'data/' out to have the filepath relative to data dir
4 index = file.find("data/") + len("data/")
5 filename_relative = file[index:]
6 source = os.path.join("./data", filename_relative)
7 target = os.path.join(data_dir, filename_relative)
8
9 env.Alias("install", target)
10 env.Command( target, source,
11 [
12 Copy("$TARGET","$SOURCE"),
13 Chmod("$TARGET", 0664),
14 ])
For best results, also make sure the umask is set like described above.
Locale files
Installing locale files on UNIX systems can be a little tricky :
This is an example that will handle installing .mo files for a source layout of /po/[language code]/app_name.mo.
1 # install .mo files
2 locale_dir = "/usr/local/share/locale"
3
4 mo_files = Glob("./po/*/app_name.mo",strings=True)
5 for mo in mo_files:
6 # extract language code
7 index_lo = mo.find("po/") + len("po/")
8 index_hi = mo.find("/app_name.mo")
9 lang_name = mo[index_lo:index_hi]
10 # copy file
11 install_location = locale_dir + "/" + lang_name + "/LC_MESSAGES/app_name.mo"
12 env.Alias("install", env.InstallAs( install_location, mo ) )
It should be simple enough to adapt this code to layouts like /po/[language code].mo or any other.
Uninstall targets
Here's a sample uninstall function :
1 def create_uninstall_target(env, path, is_glob):
2 if is_glob:
3 all_files = Glob(path,strings=True)
4 for filei in all_files:
5 env.Command( "uninstall-"+filei, filei,
6 [
7 Delete("$SOURCE"),
8 ])
9 env.Alias("uninstall", "uninstall-"+filei)
10 else:
11 env.Command( "uninstall-"+path, path,
12 [
13 Delete("$SOURCE"),
14 ])
15 env.Alias("uninstall", "uninstall-"+path)
You can use it like this :
If you want to uninstall all the files installed using Install or InstallAs, there is a more expeditive way:
1 env.Command("uninstall", None, Delete(FindInstalledFiles()))
