2010-08-20 59 views
10

我正在使用SCons來構建一個項目,並且需要爲它通過env.Install安裝的文件添加一個符號鏈接。什麼命令會創建一個鏈接,相當於在命令行上運行ln -s如何使用SCons創建符號鏈接?

回答

8

SCons的沒有一個專門的符號鏈接的命令,但你可以使用os.symlink(src, dst)從Python的os模塊:

import os 
env = Environment() 
def SymLink(target, source, env): 
    os.symlink(os.path.abspath(str(source[0])), os.path.abspath(str(target[0]))) 
env.Command("file.out", "file.in", SymLink) 

這可能無法在Windows正常工作,我只試過在Linux上。

+0

出於某種原因,試圖建立一個子目錄裏面的符號連接時,它不工作,像「env.Command(flavor +'/ Resources','src/Resources',SymLink)」的味道是'調試'或'釋放'。 – Septagram 2011-09-20 07:30:41

+1

@Septagram請參閱我的編輯 – 2011-11-26 18:30:51

+0

不適用於已安裝的文件 – RzR 2017-11-24 21:24:04

1

這將創建一個生成器來執行這項工作:

mylib = env.SharedLibrary("foobar", SRCS) 

builder = Builder(action = "ln -s ${SOURCE.file} ${TARGET.file}", chdir = True) 

env.Append(BUILDERS = {"Symlink" : builder}) 

mylib_link = env.Symlink("_foobar.so", mylib) 

env.Default(mylib) 
env.Default(mylib_link) 

此外,該解決方案是Linux。

+1

不幸的是,它在目錄上效果不佳:「TypeError:Directory/home/septi/Dropbox/Code/StreetCleaner/src/Resources預計:。「 – Septagram 2011-09-20 07:41:12

+0

@Septagram:如何解決目錄問題? – 2014-04-30 09:45:49

+0

@Nordlöw,對不起,但已經有一段時間了,我不知道:(請嘗試其他答案和評論,如果你發現的東西。 – Septagram 2014-04-30 17:48:59

7

SCons核心代碼中的符號鏈接支持似乎沒有什麼進展,我不滿意我在網上找到的任何一種解決方案。這是一個潛在的建設者,它結合了Nick和Richq的答案。此外,它會捕獲名稱更改(由於發射器方法),並且如我所能獲得的那樣與平臺無關。

我更喜歡這個構建器,因爲它會使鏈接相對於它們所在的目錄。我可以添加一個選項來強制鏈接是絕對的,但我並沒有需要或想要。目前,如果操作系統不支持符號鏈接,我只是通過並且什麼也不做,但是可以使用os.copytree()作爲例子,但是如果源是一個目錄,則依賴關係會變得混亂,因此發射器需要做一些奇特的事情。我在這裏提出任何建議。

人們可以把下面的代碼到文件site_scons/site_tools/symlink.py(空白_ 初始化 _.py文件在適當的地方)。然後做這在SConstruct文件:

SConstruct:

env = Environment() 
env.Tool('symlink') 
env.SymLink('link_name.txt', 'real_file.txt') 

symlink.py:

import os 
from os import path 

from SCons.Node import FS 
from SCons.Script import Action, Builder 

def generate(env): 
    ''' 
    SymLink(link_name,source) 
    env.SymLink(link_name,source) 

    Makes a symbolic link named "link_name" that points to the 
    real file or directory "source". The link produced is always 
    relative. 
    ''' 
    bldr = Builder(action = Action(symlink_builder,symlink_print), 
     target_factory = FS.File, 
     source_factory = FS.Entry, 
     single_target = True, 
     single_source = True, 
     emitter = symlink_emitter) 
    env.Append(BUILDERS = {'SymLink' : bldr}) 

def exists(env): 
    ''' 
    we could test if the OS supports symlinks here, or we could 
    use copytree as an alternative in the builder. 
    ''' 
    return True 

def symlink_print(target, source, env): 
    lnk = path.basename(target[0].abspath) 
    src = path.basename(source[0].abspath) 
    return 'Link: '+lnk+' points to '+src 

def symlink_emitter(target, source, env): 
    ''' 
    This emitter removes the link if the source file name has changed 
    since scons does not seem to catch this case. 
    ''' 
    lnk = target[0].abspath 
    src = source[0].abspath 
    lnkdir,lnkname = path.split(lnk) 
    srcrel = path.relpath(src,lnkdir) 

    if int(env.get('verbose',0)) > 3: 
     ldir = path.relpath(lnkdir,env.Dir('#').abspath) 
     if rellnkdir[:2] == '..': 
      ldir = path.abspath(ldir) 
     print ' symbolic link in directory: %s' % ldir 
     print '  %s -> %s' % (lnkname,srcrel) 

    try: 
     if path.exists(lnk): 
      if os.readlink(lnk) != srcrel: 
       os.remove(lnk) 
    except AttributeError: 
     # no symlink available, so we remove the whole tree? (or pass) 
     #os.rmtree(lnk) 
     print 'no os.symlink capability on this system?' 

    return (target, source) 

def symlink_builder(target, source, env): 
    lnk = target[0].abspath 
    src = source[0].abspath 
    lnkdir,lnkname = path.split(lnk) 
    srcrel = path.relpath(src,lnkdir) 

    if int(env.get('verbose',0)) > 4: 
     print 'target:', target 
     print 'source:', source 
     print 'lnk:', lnk 
     print 'src:', src 
     print 'lnkdir,lnkname:', lnkdir, lnkname 
     print 'srcrel:', srcrel 

    if int(env.get('verbose',0)) > 4: 
     print 'in directory: %s' % path.relpath(lnkdir,env.Dir('#').abspath) 
     print ' symlink: %s -> %s' % (lnkname,srcrel) 

    try: 
     os.symlink(srcrel,lnk) 
    except AttributeError: 
     # no symlink available, so we make a (deep) copy? (or pass) 
     #os.copytree(srcrel,lnk) 
     print 'no os.symlink capability on this system?' 

    return None 
+0

你寫過一硬鏈接的變種,以及?我想要內置'安裝'相同的接口,其中第一個參數是一個目錄。 – 2014-04-30 10:07:50